@wildo-ai/presets-components 1.1.5 → 1.1.6
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/esm/.native.tsbuildinfo +1 -0
- package/dist/esm/components/actions/action-bar.d.ts.map +1 -1
- package/dist/esm/components/actions/action-bar.js +5 -2
- package/dist/esm/components/actions/action-bar.js.map +1 -1
- package/dist/esm/components/ai-elements/chat/suggestion.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/chat/suggestion.js +8 -1
- package/dist/esm/components/ai-elements/chat/suggestion.js.map +1 -1
- package/dist/esm/components/ai-elements/decision/approval.d.ts +108 -13
- package/dist/esm/components/ai-elements/decision/approval.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/decision/approval.js +60 -10
- package/dist/esm/components/ai-elements/decision/approval.js.map +1 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.d.ts +3 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.js +3 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.js.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.d.ts +9 -0
- package/dist/esm/components/app/app-layout-main-container.d.ts.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.js +17 -23
- package/dist/esm/components/app/app-layout-main-container.js.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.labels.d.ts.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.labels.js +27 -0
- package/dist/esm/components/app/app-layout-main-container.labels.js.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.js +5 -2
- package/dist/esm/components/billing/billing-plan-change-preview.js.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.labels.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.labels.js +3 -0
- package/dist/esm/components/billing/billing-plan-change-preview.labels.js.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.d.ts +1 -1
- package/dist/esm/components/billing/billing-pricing-table.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.js +8 -4
- package/dist/esm/components/billing/billing-pricing-table.js.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.labels.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.labels.js +7 -1
- package/dist/esm/components/billing/billing-pricing-table.labels.js.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.js +6 -3
- package/dist/esm/components/billing/billing-usage-dashboard.js.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.labels.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.labels.js +2 -1
- package/dist/esm/components/billing/billing-usage-dashboard.labels.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-enum.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-enum.js +18 -4
- package/dist/esm/components/data-display/formatters/display-field-enum.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.js +13 -14
- package/dist/esm/components/data-display/formatters/display-field-file.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.labels.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.labels.js +1 -0
- package/dist/esm/components/data-display/formatters/display-field-file.labels.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.js +6 -1
- package/dist/esm/components/data-display/formatters/display-field-number.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.labels.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.labels.js +5 -2
- package/dist/esm/components/data-display/formatters/display-field-number.labels.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-string.d.ts +1 -1
- package/dist/esm/components/data-display/formatters/display-field-string.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-string.js +51 -12
- package/dist/esm/components/data-display/formatters/display-field-string.js.map +1 -1
- package/dist/esm/components/data-display/untrusted-html-content.d.ts +55 -0
- package/dist/esm/components/data-display/untrusted-html-content.d.ts.map +1 -0
- package/dist/esm/components/data-display/untrusted-html-content.js +67 -0
- package/dist/esm/components/data-display/untrusted-html-content.js.map +1 -0
- package/dist/esm/components/form/chromes/form-primitive.labels.d.ts.map +1 -1
- package/dist/esm/components/form/chromes/form-primitive.labels.js +9 -0
- package/dist/esm/components/form/chromes/form-primitive.labels.js.map +1 -1
- package/dist/esm/components/form/combobox.d.ts.map +1 -1
- package/dist/esm/components/form/combobox.js +10 -10
- package/dist/esm/components/form/combobox.js.map +1 -1
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.d.ts +42 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.d.ts.map +1 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.js +120 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.js.map +1 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.d.ts +16 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.d.ts.map +1 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.js +8 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.js.map +1 -0
- package/dist/esm/components/navigation/app-level/activity-bar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/activity-bar.js +2 -2
- package/dist/esm/components/navigation/app-level/activity-bar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.js +10 -4
- package/dist/esm/components/navigation/app-level/menu-user-org.js.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.labels.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.labels.js +7 -0
- package/dist/esm/components/navigation/app-level/menu-user-org.labels.js.map +1 -1
- package/dist/esm/components/navigation/app-level/menubar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/menubar.js +6 -6
- package/dist/esm/components/navigation/app-level/menubar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/navigation-back.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/navigation-back.js +27 -9
- package/dist/esm/components/navigation/app-level/navigation-back.js.map +1 -1
- package/dist/esm/components/navigation/app-level/sidebar.js +3 -3
- package/dist/esm/components/navigation/app-level/sidebar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/status-bar.js +2 -2
- package/dist/esm/components/navigation/app-level/status-bar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/toolbar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/toolbar.js +2 -2
- package/dist/esm/components/navigation/app-level/toolbar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/utility-panel.js +2 -2
- package/dist/esm/components/navigation/app-level/utility-panel.js.map +1 -1
- package/dist/esm/components/navigation/breadcrumb.js +1 -1
- package/dist/esm/components/navigation/breadcrumb.js.map +1 -1
- package/dist/esm/components/sections/stepper.d.ts.map +1 -1
- package/dist/esm/components/sections/stepper.js +5 -3
- package/dist/esm/components/sections/stepper.js.map +1 -1
- package/dist/esm/config/preset-navigation.d.ts.map +1 -1
- package/dist/esm/config/preset-navigation.js +23 -2
- package/dist/esm/config/preset-navigation.js.map +1 -1
- package/dist/esm/config/resources/agent-work.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/agent-work.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/agent-work.resource-presets.js +115 -0
- package/dist/esm/config/resources/agent-work.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/api-key-rotation-window.d.ts +22 -0
- package/dist/esm/config/resources/api-key-rotation-window.d.ts.map +1 -0
- package/dist/esm/config/resources/api-key-rotation-window.js +45 -0
- package/dist/esm/config/resources/api-key-rotation-window.js.map +1 -0
- package/dist/esm/config/resources/application.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/application.resource-presets.js +147 -61
- package/dist/esm/config/resources/application.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/billing.resource-presets.d.ts +4 -3
- package/dist/esm/config/resources/billing.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/billing.resource-presets.js +240 -111
- package/dist/esm/config/resources/billing.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/conversation-threads.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/conversation-threads.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/conversation-threads.resource-presets.js +105 -0
- package/dist/esm/config/resources/conversation-threads.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/guidance.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/guidance.resource-presets.js +18 -11
- package/dist/esm/config/resources/guidance.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/identity.resource-presets.d.ts +0 -13
- package/dist/esm/config/resources/identity.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/identity.resource-presets.js +48 -16
- package/dist/esm/config/resources/identity.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.d.ts +6 -0
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.js +112 -0
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.js +182 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/index.d.ts.map +1 -1
- package/dist/esm/config/resources/index.js +9 -2
- package/dist/esm/config/resources/index.js.map +1 -1
- package/dist/esm/config/resources/legal-holds.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/legal-holds.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/legal-holds.resource-presets.js +76 -0
- package/dist/esm/config/resources/legal-holds.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/organizations.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/organizations.resource-presets.js +139 -36
- package/dist/esm/config/resources/organizations.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/resource.config.utils.d.ts +20 -0
- package/dist/esm/config/resources/resource.config.utils.d.ts.map +1 -1
- package/dist/esm/config/resources/resource.config.utils.js +20 -0
- package/dist/esm/config/resources/resource.config.utils.js.map +1 -1
- package/dist/esm/config/resources/retention-enforcement.resource-presets.d.ts +5 -0
- package/dist/esm/config/resources/retention-enforcement.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/retention-enforcement.resource-presets.js +74 -0
- package/dist/esm/config/resources/retention-enforcement.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/security.resource-presets.d.ts +3 -1
- package/dist/esm/config/resources/security.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/security.resource-presets.js +563 -133
- package/dist/esm/config/resources/security.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/service-providers.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/service-providers.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/service-providers.resource-presets.js +321 -0
- package/dist/esm/config/resources/service-providers.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/webhooks.resource-presets.d.ts +4 -3
- package/dist/esm/config/resources/webhooks.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/webhooks.resource-presets.js +76 -25
- package/dist/esm/config/resources/webhooks.resource-presets.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/registration/register-common-enums.d.ts.map +1 -1
- package/dist/esm/registration/register-common-enums.js +15 -0
- package/dist/esm/registration/register-common-enums.js.map +1 -1
- package/dist/esm/registration/register-provider-components.d.ts.map +1 -1
- package/dist/esm/registration/register-provider-components.js +6 -0
- package/dist/esm/registration/register-provider-components.js.map +1 -1
- package/dist/esm/themes/dense.theme.d.ts.map +1 -1
- package/dist/esm/themes/dense.theme.js +22 -2
- package/dist/esm/themes/dense.theme.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -6
|
@@ -4,13 +4,14 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
4
4
|
* DisplayFieldString Component
|
|
5
5
|
*
|
|
6
6
|
* Displays a string value based on the string UI decorator.
|
|
7
|
-
* Supports different display modes: text, truncate, multiline, markdown, color, link, email, badge, copy, secret
|
|
7
|
+
* Supports different display modes: text, truncate, multiline, markdown, untrusted_html, color, link, email, badge, copy, secret
|
|
8
8
|
*/
|
|
9
9
|
import * as React from "react";
|
|
10
10
|
import { useI18n, useIconRegistry, StandardIconReference, IconSize, Text, Badge, Identifier, useContextualDisplayParams } from "@wildo-ai/saas-frontend-lib";
|
|
11
|
-
import { FrontendComponentType } from "@wildo-ai/presets-components-models";
|
|
12
|
-
import { getStringUI, getStringFormat, StringDisplayMode } from "@wildo-ai/zod-decorators";
|
|
11
|
+
import { FrontendComponentType, LabellingTypes, resolveVocabularyWordKey } from "@wildo-ai/presets-components-models";
|
|
12
|
+
import { getStringUI, getStringFormat, getSystemEnumName, StringDisplayMode } from "@wildo-ai/zod-decorators";
|
|
13
13
|
import { MarkdownContent } from "../markdown-content.js";
|
|
14
|
+
import { UntrustedHtmlContent } from "../untrusted-html-content.js";
|
|
14
15
|
/**
|
|
15
16
|
* Split a string into user-perceived characters.
|
|
16
17
|
*
|
|
@@ -27,17 +28,46 @@ function splitIntoGraphemes(value) {
|
|
|
27
28
|
return Array.from(value);
|
|
28
29
|
return Array.from(GRAPHEME_SEGMENTER.segment(value), part => part.segment);
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* The label namespaces a string display reads beyond its own component: the `roles` words an ORGANIZATION_ROLE value
|
|
33
|
+
* shows (#1921) — requested only by a field that can show one, so no other string display waits on the roles bundle.
|
|
34
|
+
* Module-level so each requested set keeps one identity across renders.
|
|
35
|
+
*/
|
|
36
|
+
const ROLE_LABEL_NAMESPACES = [LabellingTypes.ROLES];
|
|
37
|
+
const NO_EXTRA_LABEL_NAMESPACES = [];
|
|
30
38
|
/**
|
|
31
39
|
* DisplayFieldString component
|
|
32
40
|
*
|
|
33
41
|
* Renders a string value according to the string UI decorator
|
|
34
42
|
*/
|
|
35
43
|
function DisplayFieldString({ schema, value, className, }) {
|
|
36
|
-
const
|
|
44
|
+
const stringUI = getStringUI(schema);
|
|
45
|
+
const showsRole = stringUI?.display?.displayMode === StringDisplayMode.ORGANIZATION_ROLE
|
|
46
|
+
|| stringUI?.summaryOverride?.displayMode === StringDisplayMode.ORGANIZATION_ROLE;
|
|
47
|
+
const { tComponent, tRole, t, isReady } = useI18n({
|
|
48
|
+
component: [FrontendComponentType.LOW_LEVEL_FORM_FIELD, FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING],
|
|
49
|
+
keys: showsRole ? ROLE_LABEL_NAMESPACES : NO_EXTRA_LABEL_NAMESPACES,
|
|
50
|
+
});
|
|
37
51
|
const { renderIcon } = useIconRegistry();
|
|
38
52
|
const [copied, setCopied] = React.useState(false);
|
|
39
|
-
const stringUI = getStringUI(schema);
|
|
40
53
|
const stringFormat = getStringFormat(schema);
|
|
54
|
+
/*
|
|
55
|
+
* An OPEN vocabulary (#1791): the string's values are words of a vocabulary declared outside the schema — today the
|
|
56
|
+
* engine's audit event types — named with `.systemEnum(name)`. Read as a word where the vocabulary keeps it
|
|
57
|
+
* (`resolveVocabularyWordKey`: `system_enums.<name>.<value>`, or a feature's and a limit's own billing section) in
|
|
58
|
+
* every mode that shows the value as prose (text, truncate, multiline, badge, the default); a missing word shows
|
|
59
|
+
* the value, which is the missing label looking missing. Modes that show the value AS DATA keep it raw on purpose:
|
|
60
|
+
* copy, identifier, link, email, secret, markdown, untrusted HTML, colour. Every one of those sections is eager
|
|
61
|
+
* (`EAGER_I18N_SECTIONS`), so this needs no extra request.
|
|
62
|
+
*/
|
|
63
|
+
const openVocabulary = schema ? getSystemEnumName(schema) : undefined;
|
|
64
|
+
const asWord = (raw) => {
|
|
65
|
+
if (!openVocabulary)
|
|
66
|
+
return raw;
|
|
67
|
+
const key = resolveVocabularyWordKey(openVocabulary, raw);
|
|
68
|
+
const word = t(key);
|
|
69
|
+
return word === key ? raw : word;
|
|
70
|
+
};
|
|
41
71
|
// SECRET fields mask by default; `initiallyRevealed` (set by `.isEphemeral()`)
|
|
42
72
|
// shows the value on first paint for one-time reveals. The eye toggle still works.
|
|
43
73
|
const stringDisplayParams = useContextualDisplayParams(stringUI);
|
|
@@ -66,7 +96,7 @@ function DisplayFieldString({ schema, value, className, }) {
|
|
|
66
96
|
// Render based on display mode
|
|
67
97
|
switch (displayMode) {
|
|
68
98
|
case StringDisplayMode.TEXT:
|
|
69
|
-
return _jsx(Text, { children: value });
|
|
99
|
+
return _jsx(Text, { children: asWord(value) });
|
|
70
100
|
case StringDisplayMode.TRUNCATE: {
|
|
71
101
|
// TWO AXES, BOTH LIVE, AND THEY ARE NOT THE SAME QUESTION.
|
|
72
102
|
//
|
|
@@ -94,13 +124,15 @@ function DisplayFieldString({ schema, value, className, }) {
|
|
|
94
124
|
// rejected. `Intl.Segmenter` counts and cuts what a reader would call a character: an emoji
|
|
95
125
|
// with a skin-tone modifier, a family joined by ZWJ, a flag's two regional indicators, and a
|
|
96
126
|
// letter with its combining accent are each one.
|
|
127
|
+
// What is shown, and cut: an open-vocabulary value's WORD (#1791), otherwise the value itself.
|
|
128
|
+
const shown = asWord(value);
|
|
97
129
|
const maximumCharacters = stringDisplayParams?.truncateLength;
|
|
98
130
|
const graphemes = typeof maximumCharacters === 'number' && maximumCharacters > 0
|
|
99
|
-
? splitIntoGraphemes(
|
|
131
|
+
? splitIntoGraphemes(shown)
|
|
100
132
|
: null;
|
|
101
133
|
const clipsAtCharacterCount = graphemes !== null && typeof maximumCharacters === 'number' && graphemes.length > maximumCharacters;
|
|
102
134
|
if (!clipsAtCharacterCount) {
|
|
103
|
-
return (_jsx(Text, { className: "min-w-0 truncate", children:
|
|
135
|
+
return (_jsx(Text, { className: "min-w-0 truncate", children: shown }));
|
|
104
136
|
}
|
|
105
137
|
// `title` carries the full value, and it is not decoration: a character cap REMOVES the
|
|
106
138
|
// remainder from the DOM, where a CSS clip only hides it, so without this there is nothing
|
|
@@ -118,10 +150,14 @@ function DisplayFieldString({ schema, value, className, }) {
|
|
|
118
150
|
// overflows, so that tooltip stops opening and the native `title` is what remains. The full
|
|
119
151
|
// value stays reachable either way; the polish of which tooltip shows it does not survive
|
|
120
152
|
// the cap, and an author choosing `truncateLength` on such a surface is choosing that.
|
|
121
|
-
return (_jsx(Text, { className: "min-w-0 truncate", title:
|
|
153
|
+
return (_jsx(Text, { className: "min-w-0 truncate", title: shown, children: `${(graphemes ?? []).slice(0, maximumCharacters).join('').trimEnd()}…` }));
|
|
122
154
|
}
|
|
155
|
+
case StringDisplayMode.ORGANIZATION_ROLE:
|
|
156
|
+
// #1921 — a key of the organization role table, read as the role's word from the `roles` labels (the member
|
|
157
|
+
// directory's words). A role with no authored word shows its key: a missing label that looks missing.
|
|
158
|
+
return _jsx(Text, { children: tRole(value, 'label') });
|
|
123
159
|
case StringDisplayMode.MULTILINE:
|
|
124
|
-
return (_jsx(Text, { className: "whitespace-pre-wrap", children: value }));
|
|
160
|
+
return (_jsx(Text, { className: "whitespace-pre-wrap", children: asWord(value) }));
|
|
125
161
|
case StringDisplayMode.IDENTIFIER:
|
|
126
162
|
// A machine ref/slug: verbatim and greppable, styled to recede behind the prose.
|
|
127
163
|
//
|
|
@@ -137,6 +173,9 @@ function DisplayFieldString({ schema, value, className, }) {
|
|
|
137
173
|
// themed through the typography recipes. See markdown-content.tsx for
|
|
138
174
|
// the embedded heading-demotion rationale.
|
|
139
175
|
return _jsx(MarkdownContent, { value: value });
|
|
176
|
+
case StringDisplayMode.UNTRUSTED_HTML:
|
|
177
|
+
// HTML from outside the application (a received email body, #1912): sandboxed, no remote content.
|
|
178
|
+
return _jsx(UntrustedHtmlContent, { value: value, title: tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'untrustedHtmlFrameTitle') });
|
|
140
179
|
case StringDisplayMode.COLOR:
|
|
141
180
|
return (_jsxs("div", { className: "flex items-center gap-element", children: [_jsx("div", { className: "h-5 w-5 rounded border border-border", style: { backgroundColor: value }, "aria-hidden": "true" }), _jsx(Text, { className: "font-mono text-sm", children: value })] }));
|
|
142
181
|
case StringDisplayMode.LINK:
|
|
@@ -144,7 +183,7 @@ function DisplayFieldString({ schema, value, className, }) {
|
|
|
144
183
|
case StringDisplayMode.EMAIL:
|
|
145
184
|
return (_jsx("a", { href: `mailto:${value}`, className: "text-primary hover:underline", children: value }));
|
|
146
185
|
case StringDisplayMode.BADGE:
|
|
147
|
-
return _jsx(Badge, { variant: "secondary", children: value });
|
|
186
|
+
return _jsx(Badge, { variant: "secondary", children: asWord(value) });
|
|
148
187
|
case StringDisplayMode.COPY:
|
|
149
188
|
return (_jsxs("div", { className: "flex items-center gap-element", children: [_jsx(Text, { className: "font-mono text-sm", children: value }), _jsx("button", { type: "button", onClick: handleCopy, className: "text-muted-foreground hover:text-foreground transition-colors", "aria-label": copied ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copied') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copyToClipboard'), children: _jsx("span", { "aria-hidden": "true", children: copied
|
|
150
189
|
? renderIcon(StandardIconReference.CHECK, { size: IconSize.SM })
|
|
@@ -156,7 +195,7 @@ function DisplayFieldString({ schema, value, className, }) {
|
|
|
156
195
|
? renderIcon(StandardIconReference.CHECK, { size: IconSize.SM })
|
|
157
196
|
: renderIcon(StandardIconReference.COPY, { size: IconSize.SM }) }) })] }));
|
|
158
197
|
default:
|
|
159
|
-
return _jsx(Text, { children: value });
|
|
198
|
+
return _jsx(Text, { children: asWord(value) });
|
|
160
199
|
}
|
|
161
200
|
};
|
|
162
201
|
if (!isReady)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display-field-string.js","sourceRoot":"","sources":["../../../../../../src/components/data-display/formatters/display-field-string.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\n/**\n * DisplayFieldString Component\n *\n * Displays a string value based on the string UI decorator.\n * Supports different display modes: text, truncate, multiline, markdown, color, link, email, badge, copy, secret\n */\n\nimport * as React from \"react\"\n\nimport { cn, useI18n, useIconRegistry, StandardIconReference, IconSize, Text, Badge, Identifier, useContextualDisplayParams} from \"@wildo-ai/saas-frontend-lib\"\nimport { FrontendComponentType } from \"@wildo-ai/presets-components-models\"\nimport { getStringUI, getStringFormat, StringDisplayMode } from \"@wildo-ai/zod-decorators\"\nimport type { DisplayFieldStringProps } from '@wildo-ai/saas-frontend-lib'\n\nimport { MarkdownContent } from \"../markdown-content\"\n\n/**\n * Split a string into user-perceived characters.\n *\n * `Intl.Segmenter` is the only thing that gets this right — code units split surrogate pairs, and\n * code points still split a flag, a ZWJ sequence, a skin-tone modifier and a combining accent. The\n * fallback to code points is for a runtime without it; it is strictly better than code units and\n * cannot produce a lone surrogate, which is the failure that actually shows on screen.\n */\nconst GRAPHEME_SEGMENTER =\n typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function'\n ? new Intl.Segmenter(undefined, { granularity: 'grapheme' })\n : null\n\nfunction splitIntoGraphemes(value: string): string[] {\n if (!GRAPHEME_SEGMENTER) return Array.from(value)\n return Array.from(GRAPHEME_SEGMENTER.segment(value), part => part.segment)\n}\n\n/**\n * DisplayFieldString component\n *\n * Renders a string value according to the string UI decorator\n */\nfunction DisplayFieldString({\n schema,\n value,\n className,\n}: DisplayFieldStringProps): React.JSX.Element | null {\n const { tComponent, isReady } = useI18n({ component: [FrontendComponentType.LOW_LEVEL_FORM_FIELD, FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING] })\n const { renderIcon } = useIconRegistry()\n const [copied, setCopied] = React.useState(false)\n\n const stringUI = getStringUI(schema)\n const stringFormat = getStringFormat(schema)\n\n // SECRET fields mask by default; `initiallyRevealed` (set by `.isEphemeral()`)\n // shows the value on first paint for one-time reveals. The eye toggle still works.\n const stringDisplayParams = useContextualDisplayParams(stringUI)\n const [revealed, setRevealed] = React.useState(stringDisplayParams?.initiallyRevealed ?? false)\n\n let displayMode = stringDisplayParams?.displayMode ?? StringDisplayMode.TEXT\n if (!stringUI && stringFormat) {\n if (stringFormat === 'email') displayMode = StringDisplayMode.EMAIL\n else if (stringFormat === 'url') displayMode = StringDisplayMode.LINK\n }\n\n // Copy to clipboard handler\n const handleCopy = async () => {\n if (value) {\n await navigator.clipboard.writeText(value)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n // Render the value content\n const renderValue = () => {\n // Handle null/undefined\n if (value === null || value === undefined || value === '') {\n return <><Text className=\"text-muted-foreground italic\" aria-hidden=\"true\">—</Text><span className=\"sr-only\">{tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD, 'noValue')}</span></>\n }\n\n // Render based on display mode\n switch (displayMode) {\n case StringDisplayMode.TEXT:\n return <Text>{value}</Text>\n\n case StringDisplayMode.TRUNCATE: {\n // TWO AXES, BOTH LIVE, AND THEY ARE NOT THE SAME QUESTION.\n //\n // The `truncate` class below is a WIDTH cap: it clips to whatever the container can\n // show, so it is responsive and never cuts a value that fits. `truncateLength` is a\n // CHARACTER cap — its declaration says \"Max characters before truncation\" — so it is a\n // statement about the VALUE and holds at any width. Applying both gives the shorter of\n // the two, which is what an author asking for either one expects.\n //\n // The `ch`-based width ceiling considered as an alternative was rejected: a `ch` is the\n // advance of \"0\", so against a proportional font `truncateLength: 48` would show\n // anywhere from roughly thirty to eighty characters. That makes a parameter documented\n // as a character count mean something it does not say, which is the kind of near-miss\n // semantics the framework refuses.\n //\n // The ellipsis is ADDITIONAL to the budget: `truncateLength: 48` yields 48 characters\n // of the value plus the mark that more exists, which is how a \"max characters\" cap\n // reads everywhere else. `trimEnd` so a cut landing mid-space does not render \"abc …\".\n //\n // A CHARACTER IS A GRAPHEME, not a UTF-16 code unit, and the difference is not academic.\n // `value.slice(0, n)` cuts between the two halves of a surrogate pair, so a string of emoji\n // rendered at `truncateLength: 3` came out as `👍�…` — a literal replacement glyph. It also\n // counted `\"🎉🎉🎉\"` as six characters, which made this parameter mean something other than\n // what its own declaration says, for exactly the reason the `ch`-based alternative was\n // rejected. `Intl.Segmenter` counts and cuts what a reader would call a character: an emoji\n // with a skin-tone modifier, a family joined by ZWJ, a flag's two regional indicators, and a\n // letter with its combining accent are each one.\n const maximumCharacters = stringDisplayParams?.truncateLength\n const graphemes = typeof maximumCharacters === 'number' && maximumCharacters > 0\n ? splitIntoGraphemes(value)\n : null\n const clipsAtCharacterCount =\n graphemes !== null && typeof maximumCharacters === 'number' && graphemes.length > maximumCharacters\n\n if (!clipsAtCharacterCount) {\n return (\n <Text className=\"min-w-0 truncate\">\n {value}\n </Text>\n )\n }\n\n // `title` carries the full value, and it is not decoration: a character cap REMOVES the\n // remainder from the DOM, where a CSS clip only hides it, so without this there is nothing\n // left holding the rest of the string.\n //\n // Be precise about what it does and does not restore, because an earlier version of this\n // comment overclaimed and a review caught it. `title` is an ATTRIBUTE, so browser\n // find-in-page — which searches rendered text — does NOT match the hidden remainder, and a\n // screen reader's treatment of `title` on a `<p>` is inconsistent and never keyboard\n // reachable. It is the strongest affordance available on this element, not an equivalent of\n // leaving the text in place.\n //\n // On a surface whose policy sets `tooltipOnTruncate`, `Text` routes its children into a\n // styled tooltip when the element OVERFLOWS. A character-capped string usually no longer\n // overflows, so that tooltip stops opening and the native `title` is what remains. The full\n // value stays reachable either way; the polish of which tooltip shows it does not survive\n // the cap, and an author choosing `truncateLength` on such a surface is choosing that.\n return (\n <Text className=\"min-w-0 truncate\" title={value}>\n {`${(graphemes ?? []).slice(0, maximumCharacters).join('').trimEnd()}…`}\n </Text>\n )\n }\n\n case StringDisplayMode.MULTILINE:\n return (\n <Text className=\"whitespace-pre-wrap\">\n {value}\n </Text>\n )\n\n case StringDisplayMode.IDENTIFIER:\n // A machine ref/slug: verbatim and greppable, styled to recede behind the prose.\n //\n // Through the `Identifier` element rather than a class string, and that is the whole point of\n // that element existing: this treatment used to live ONLY here, inside a switch nothing\n // outside the field pipeline can call, so every surface that builds its own rows spelled the\n // same classes by hand and drifted. One resolved component is what lets a hand-built row and\n // a field render the same ref the same way — and makes the treatment themeable, which a\n // class string in a switch never was.\n return <Identifier>{value}</Identifier>\n\n case StringDisplayMode.MARKDOWN:\n // Rich long-form content (descriptions, notes): full markdown body\n // themed through the typography recipes. See markdown-content.tsx for\n // the embedded heading-demotion rationale.\n return <MarkdownContent value={value} />\n\n\n case StringDisplayMode.COLOR:\n return (\n <div className=\"flex items-center gap-element\">\n <div\n className=\"h-5 w-5 rounded border border-border\"\n style={{ backgroundColor: value }}\n aria-hidden=\"true\"\n />\n <Text className=\"font-mono text-sm\">{value}</Text>\n </div>\n )\n\n case StringDisplayMode.LINK:\n return (\n <a\n href={value}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n >\n {value}\n </a>\n )\n\n case StringDisplayMode.EMAIL:\n return (\n <a\n href={`mailto:${value}`}\n className=\"text-primary hover:underline\"\n >\n {value}\n </a>\n )\n\n case StringDisplayMode.BADGE:\n return <Badge variant=\"secondary\">{value}</Badge>\n\n case StringDisplayMode.COPY:\n return (\n <div className=\"flex items-center gap-element\">\n <Text className=\"font-mono text-sm\">{value}</Text>\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={copied ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copied') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copyToClipboard')}\n >\n <span aria-hidden=\"true\">\n {copied\n ? renderIcon(StandardIconReference.CHECK, { size: IconSize.SM })\n : renderIcon(StandardIconReference.COPY, { size: IconSize.SM })\n }\n </span>\n </button>\n </div>\n )\n\n case StringDisplayMode.SECRET:\n return (\n <div className=\"flex items-center gap-element\">\n <Text className=\"font-mono text-sm select-all\" aria-live=\"polite\">\n {revealed ? value : '••••••••••••••••'}\n </Text>\n <button\n type=\"button\"\n onClick={() => setRevealed(prev => !prev)}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={revealed ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'hideValue') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'revealValue')}\n >\n <span aria-hidden=\"true\">\n {revealed\n ? renderIcon(StandardIconReference.EYE_OFF, { size: IconSize.SM })\n : renderIcon(StandardIconReference.EYE, { size: IconSize.SM })\n }\n </span>\n </button>\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={copied ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copied') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copyToClipboard')}\n >\n <span aria-hidden=\"true\">\n {copied\n ? renderIcon(StandardIconReference.CHECK, { size: IconSize.SM })\n : renderIcon(StandardIconReference.COPY, { size: IconSize.SM })\n }\n </span>\n </button>\n </div>\n )\n\n default:\n return <Text>{value}</Text>\n }\n }\n\n if (!isReady) return null\n // Label/description rendering is handled by the parent DisplayField (FIELD-01)\n return <div className={className}>{renderValue()}</div>\n}\n\n;(DisplayFieldString as typeof DisplayFieldString & { displayName: string }).displayName = \"DisplayFieldString\"\n\nexport { DisplayFieldString }\n"]}
|
|
1
|
+
{"version":3,"file":"display-field-string.js","sourceRoot":"","sources":["../../../../../../src/components/data-display/formatters/display-field-string.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\n/**\n * DisplayFieldString Component\n *\n * Displays a string value based on the string UI decorator.\n * Supports different display modes: text, truncate, multiline, markdown, untrusted_html, color, link, email, badge, copy, secret\n */\n\nimport * as React from \"react\"\n\nimport { cn, useI18n, useIconRegistry, StandardIconReference, IconSize, Text, Badge, Identifier, useContextualDisplayParams} from \"@wildo-ai/saas-frontend-lib\"\nimport { FrontendComponentType, LabellingTypes, resolveVocabularyWordKey } from \"@wildo-ai/presets-components-models\"\nimport { getStringUI, getStringFormat, getSystemEnumName, StringDisplayMode } from \"@wildo-ai/zod-decorators\"\nimport type { DisplayFieldStringProps } from '@wildo-ai/saas-frontend-lib'\n\nimport { MarkdownContent } from \"../markdown-content\"\nimport { UntrustedHtmlContent } from \"../untrusted-html-content\"\n\n/**\n * Split a string into user-perceived characters.\n *\n * `Intl.Segmenter` is the only thing that gets this right — code units split surrogate pairs, and\n * code points still split a flag, a ZWJ sequence, a skin-tone modifier and a combining accent. The\n * fallback to code points is for a runtime without it; it is strictly better than code units and\n * cannot produce a lone surrogate, which is the failure that actually shows on screen.\n */\nconst GRAPHEME_SEGMENTER =\n typeof Intl !== 'undefined' && typeof Intl.Segmenter === 'function'\n ? new Intl.Segmenter(undefined, { granularity: 'grapheme' })\n : null\n\nfunction splitIntoGraphemes(value: string): string[] {\n if (!GRAPHEME_SEGMENTER) return Array.from(value)\n return Array.from(GRAPHEME_SEGMENTER.segment(value), part => part.segment)\n}\n\n/**\n * The label namespaces a string display reads beyond its own component: the `roles` words an ORGANIZATION_ROLE value\n * shows (#1921) — requested only by a field that can show one, so no other string display waits on the roles bundle.\n * Module-level so each requested set keeps one identity across renders.\n */\nconst ROLE_LABEL_NAMESPACES = [LabellingTypes.ROLES]\nconst NO_EXTRA_LABEL_NAMESPACES: LabellingTypes[] = []\n\n/**\n * DisplayFieldString component\n *\n * Renders a string value according to the string UI decorator\n */\nfunction DisplayFieldString({\n schema,\n value,\n className,\n}: DisplayFieldStringProps): React.JSX.Element | null {\n const stringUI = getStringUI(schema)\n const showsRole = stringUI?.display?.displayMode === StringDisplayMode.ORGANIZATION_ROLE\n || stringUI?.summaryOverride?.displayMode === StringDisplayMode.ORGANIZATION_ROLE\n const { tComponent, tRole, t, isReady } = useI18n({\n component: [FrontendComponentType.LOW_LEVEL_FORM_FIELD, FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING],\n keys: showsRole ? ROLE_LABEL_NAMESPACES : NO_EXTRA_LABEL_NAMESPACES,\n })\n const { renderIcon } = useIconRegistry()\n const [copied, setCopied] = React.useState(false)\n\n const stringFormat = getStringFormat(schema)\n\n /*\n * An OPEN vocabulary (#1791): the string's values are words of a vocabulary declared outside the schema — today the\n * engine's audit event types — named with `.systemEnum(name)`. Read as a word where the vocabulary keeps it\n * (`resolveVocabularyWordKey`: `system_enums.<name>.<value>`, or a feature's and a limit's own billing section) in\n * every mode that shows the value as prose (text, truncate, multiline, badge, the default); a missing word shows\n * the value, which is the missing label looking missing. Modes that show the value AS DATA keep it raw on purpose:\n * copy, identifier, link, email, secret, markdown, untrusted HTML, colour. Every one of those sections is eager\n * (`EAGER_I18N_SECTIONS`), so this needs no extra request.\n */\n const openVocabulary = schema ? getSystemEnumName(schema) : undefined\n const asWord = (raw: string): string => {\n if (!openVocabulary) return raw\n const key = resolveVocabularyWordKey(openVocabulary, raw)\n const word = t(key)\n return word === key ? raw : word\n }\n\n // SECRET fields mask by default; `initiallyRevealed` (set by `.isEphemeral()`)\n // shows the value on first paint for one-time reveals. The eye toggle still works.\n const stringDisplayParams = useContextualDisplayParams(stringUI)\n const [revealed, setRevealed] = React.useState(stringDisplayParams?.initiallyRevealed ?? false)\n\n let displayMode = stringDisplayParams?.displayMode ?? StringDisplayMode.TEXT\n if (!stringUI && stringFormat) {\n if (stringFormat === 'email') displayMode = StringDisplayMode.EMAIL\n else if (stringFormat === 'url') displayMode = StringDisplayMode.LINK\n }\n\n // Copy to clipboard handler\n const handleCopy = async () => {\n if (value) {\n await navigator.clipboard.writeText(value)\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n // Render the value content\n const renderValue = () => {\n // Handle null/undefined\n if (value === null || value === undefined || value === '') {\n return <><Text className=\"text-muted-foreground italic\" aria-hidden=\"true\">—</Text><span className=\"sr-only\">{tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD, 'noValue')}</span></>\n }\n\n // Render based on display mode\n switch (displayMode) {\n case StringDisplayMode.TEXT:\n return <Text>{asWord(value)}</Text>\n\n case StringDisplayMode.TRUNCATE: {\n // TWO AXES, BOTH LIVE, AND THEY ARE NOT THE SAME QUESTION.\n //\n // The `truncate` class below is a WIDTH cap: it clips to whatever the container can\n // show, so it is responsive and never cuts a value that fits. `truncateLength` is a\n // CHARACTER cap — its declaration says \"Max characters before truncation\" — so it is a\n // statement about the VALUE and holds at any width. Applying both gives the shorter of\n // the two, which is what an author asking for either one expects.\n //\n // The `ch`-based width ceiling considered as an alternative was rejected: a `ch` is the\n // advance of \"0\", so against a proportional font `truncateLength: 48` would show\n // anywhere from roughly thirty to eighty characters. That makes a parameter documented\n // as a character count mean something it does not say, which is the kind of near-miss\n // semantics the framework refuses.\n //\n // The ellipsis is ADDITIONAL to the budget: `truncateLength: 48` yields 48 characters\n // of the value plus the mark that more exists, which is how a \"max characters\" cap\n // reads everywhere else. `trimEnd` so a cut landing mid-space does not render \"abc …\".\n //\n // A CHARACTER IS A GRAPHEME, not a UTF-16 code unit, and the difference is not academic.\n // `value.slice(0, n)` cuts between the two halves of a surrogate pair, so a string of emoji\n // rendered at `truncateLength: 3` came out as `👍�…` — a literal replacement glyph. It also\n // counted `\"🎉🎉🎉\"` as six characters, which made this parameter mean something other than\n // what its own declaration says, for exactly the reason the `ch`-based alternative was\n // rejected. `Intl.Segmenter` counts and cuts what a reader would call a character: an emoji\n // with a skin-tone modifier, a family joined by ZWJ, a flag's two regional indicators, and a\n // letter with its combining accent are each one.\n // What is shown, and cut: an open-vocabulary value's WORD (#1791), otherwise the value itself.\n const shown = asWord(value)\n const maximumCharacters = stringDisplayParams?.truncateLength\n const graphemes = typeof maximumCharacters === 'number' && maximumCharacters > 0\n ? splitIntoGraphemes(shown)\n : null\n const clipsAtCharacterCount =\n graphemes !== null && typeof maximumCharacters === 'number' && graphemes.length > maximumCharacters\n\n if (!clipsAtCharacterCount) {\n return (\n <Text className=\"min-w-0 truncate\">\n {shown}\n </Text>\n )\n }\n\n // `title` carries the full value, and it is not decoration: a character cap REMOVES the\n // remainder from the DOM, where a CSS clip only hides it, so without this there is nothing\n // left holding the rest of the string.\n //\n // Be precise about what it does and does not restore, because an earlier version of this\n // comment overclaimed and a review caught it. `title` is an ATTRIBUTE, so browser\n // find-in-page — which searches rendered text — does NOT match the hidden remainder, and a\n // screen reader's treatment of `title` on a `<p>` is inconsistent and never keyboard\n // reachable. It is the strongest affordance available on this element, not an equivalent of\n // leaving the text in place.\n //\n // On a surface whose policy sets `tooltipOnTruncate`, `Text` routes its children into a\n // styled tooltip when the element OVERFLOWS. A character-capped string usually no longer\n // overflows, so that tooltip stops opening and the native `title` is what remains. The full\n // value stays reachable either way; the polish of which tooltip shows it does not survive\n // the cap, and an author choosing `truncateLength` on such a surface is choosing that.\n return (\n <Text className=\"min-w-0 truncate\" title={shown}>\n {`${(graphemes ?? []).slice(0, maximumCharacters).join('').trimEnd()}…`}\n </Text>\n )\n }\n\n case StringDisplayMode.ORGANIZATION_ROLE:\n // #1921 — a key of the organization role table, read as the role's word from the `roles` labels (the member\n // directory's words). A role with no authored word shows its key: a missing label that looks missing.\n return <Text>{tRole(value, 'label')}</Text>\n\n case StringDisplayMode.MULTILINE:\n return (\n <Text className=\"whitespace-pre-wrap\">\n {asWord(value)}\n </Text>\n )\n\n case StringDisplayMode.IDENTIFIER:\n // A machine ref/slug: verbatim and greppable, styled to recede behind the prose.\n //\n // Through the `Identifier` element rather than a class string, and that is the whole point of\n // that element existing: this treatment used to live ONLY here, inside a switch nothing\n // outside the field pipeline can call, so every surface that builds its own rows spelled the\n // same classes by hand and drifted. One resolved component is what lets a hand-built row and\n // a field render the same ref the same way — and makes the treatment themeable, which a\n // class string in a switch never was.\n return <Identifier>{value}</Identifier>\n\n case StringDisplayMode.MARKDOWN:\n // Rich long-form content (descriptions, notes): full markdown body\n // themed through the typography recipes. See markdown-content.tsx for\n // the embedded heading-demotion rationale.\n return <MarkdownContent value={value} />\n\n case StringDisplayMode.UNTRUSTED_HTML:\n // HTML from outside the application (a received email body, #1912): sandboxed, no remote content.\n return <UntrustedHtmlContent value={value} title={tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'untrustedHtmlFrameTitle')} />\n\n\n case StringDisplayMode.COLOR:\n return (\n <div className=\"flex items-center gap-element\">\n <div\n className=\"h-5 w-5 rounded border border-border\"\n style={{ backgroundColor: value }}\n aria-hidden=\"true\"\n />\n <Text className=\"font-mono text-sm\">{value}</Text>\n </div>\n )\n\n case StringDisplayMode.LINK:\n return (\n <a\n href={value}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n >\n {value}\n </a>\n )\n\n case StringDisplayMode.EMAIL:\n return (\n <a\n href={`mailto:${value}`}\n className=\"text-primary hover:underline\"\n >\n {value}\n </a>\n )\n\n case StringDisplayMode.BADGE:\n return <Badge variant=\"secondary\">{asWord(value)}</Badge>\n\n case StringDisplayMode.COPY:\n return (\n <div className=\"flex items-center gap-element\">\n <Text className=\"font-mono text-sm\">{value}</Text>\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={copied ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copied') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copyToClipboard')}\n >\n <span aria-hidden=\"true\">\n {copied\n ? renderIcon(StandardIconReference.CHECK, { size: IconSize.SM })\n : renderIcon(StandardIconReference.COPY, { size: IconSize.SM })\n }\n </span>\n </button>\n </div>\n )\n\n case StringDisplayMode.SECRET:\n return (\n <div className=\"flex items-center gap-element\">\n <Text className=\"font-mono text-sm select-all\" aria-live=\"polite\">\n {revealed ? value : '••••••••••••••••'}\n </Text>\n <button\n type=\"button\"\n onClick={() => setRevealed(prev => !prev)}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={revealed ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'hideValue') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'revealValue')}\n >\n <span aria-hidden=\"true\">\n {revealed\n ? renderIcon(StandardIconReference.EYE_OFF, { size: IconSize.SM })\n : renderIcon(StandardIconReference.EYE, { size: IconSize.SM })\n }\n </span>\n </button>\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={copied ? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copied') : tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD_STRING, 'copyToClipboard')}\n >\n <span aria-hidden=\"true\">\n {copied\n ? renderIcon(StandardIconReference.CHECK, { size: IconSize.SM })\n : renderIcon(StandardIconReference.COPY, { size: IconSize.SM })\n }\n </span>\n </button>\n </div>\n )\n\n default:\n return <Text>{asWord(value)}</Text>\n }\n }\n\n if (!isReady) return null\n // Label/description rendering is handled by the parent DisplayField (FIELD-01)\n return <div className={className}>{renderValue()}</div>\n}\n\n;(DisplayFieldString as typeof DisplayFieldString & { displayName: string }).displayName = \"DisplayFieldString\"\n\nexport { DisplayFieldString }\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UntrustedHtmlContent — renders HTML a STRANGER wrote (the HTML part of a received email, #1600) without letting it
|
|
3
|
+
* run, reach the network, or restyle the application (#1912).
|
|
4
|
+
*
|
|
5
|
+
* ## What a mail client does, and what this does
|
|
6
|
+
*
|
|
7
|
+
* Every mainstream mail client refuses remote content in received mail by default: Thunderbird blocks it and shows a
|
|
8
|
+
* "remote content" bar, Apple Mail's Mail Privacy Protection and Gmail's image proxy exist because a remote image is
|
|
9
|
+
* a read receipt (it tells the sender WHEN the message was opened and FROM WHICH address). Browser-based clients do it
|
|
10
|
+
* by rendering the message in a sandboxed frame with a content-security policy that allows no fetch at all. This does
|
|
11
|
+
* the same, with the browser as the enforcer rather than a rewrite pass:
|
|
12
|
+
*
|
|
13
|
+
* - `<iframe sandbox>` WITHOUT `allow-scripts` and WITHOUT `allow-same-origin`: nothing in the message executes, and
|
|
14
|
+
* the frame is an opaque origin that can read neither the application's DOM, cookies nor storage;
|
|
15
|
+
* - a CSP meta as the frame's first element — `default-src 'none'`: no image, stylesheet, font, media or frame is
|
|
16
|
+
* fetched from anywhere. Only inline `data:` images and inline `<style>` are allowed;
|
|
17
|
+
* - `<base target="_blank">` with `allow-popups` / `allow-popups-to-escape-sandbox`: a link the reader CLICKS opens in a
|
|
18
|
+
* new tab (a reader's own act, not the message's); a form never submits (no `allow-forms`).
|
|
19
|
+
*
|
|
20
|
+
* spec-cite: HTML Living Standard §4.8.5 "The iframe element" — the `sandbox` attribute's flags (`allow-scripts`,
|
|
21
|
+
* `allow-same-origin`, `allow-popups`, `allow-popups-to-escape-sandbox`, `allow-forms`) and the opaque origin a frame
|
|
22
|
+
* without `allow-same-origin` receives. https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox
|
|
23
|
+
*
|
|
24
|
+
* ## Rejected: sanitizing into the page (drop `<style>`, strip remote `src`)
|
|
25
|
+
*
|
|
26
|
+
* The first reading surface ran the HTML through the markdown pipeline's `rehype-sanitize`, which keeps images and
|
|
27
|
+
* UNWRAPS a `<style>` element into visible text. Tightening that schema (drop `<style>`, strip every remote `src`,
|
|
28
|
+
* `srcset`, `background` and CSS `url()`) was considered and rejected: it is a hand-kept list of ways HTML reaches the
|
|
29
|
+
* network, and it would still inject the message's markup into the application's own DOM, where a missed
|
|
30
|
+
* vector is a leak and a `position: fixed` rule is a clickjacking overlay. The frame makes the browser enforce
|
|
31
|
+
* "no fetch" for every vector at once, and scopes the message's styles to itself — which is why they are KEPT rather
|
|
32
|
+
* than dropped: a styled newsletter stays readable and cannot touch the page around it.
|
|
33
|
+
*
|
|
34
|
+
* Remote content has no opt-in here. Blocking it always is the stricter half of what mail clients do; an explicit
|
|
35
|
+
* "load remote content" action would be a separate, deliberate addition.
|
|
36
|
+
*/
|
|
37
|
+
import * as React from "react";
|
|
38
|
+
/**
|
|
39
|
+
* The frame's policy. `img-src data:` keeps inline images a message carries in its own body; nothing else loads.
|
|
40
|
+
* `style-src 'unsafe-inline'` lets the message's own `<style>` apply INSIDE the frame only.
|
|
41
|
+
*/
|
|
42
|
+
export declare const UNTRUSTED_HTML_CONTENT_SECURITY_POLICY = "default-src 'none'; img-src data:; style-src 'unsafe-inline'; font-src data:";
|
|
43
|
+
/** The sandbox flags: links a reader clicks may open a new tab, and nothing else is granted. */
|
|
44
|
+
export declare const UNTRUSTED_HTML_SANDBOX = "allow-popups allow-popups-to-escape-sandbox";
|
|
45
|
+
/** The document the frame renders: the policy FIRST, so it governs everything after it. */
|
|
46
|
+
export declare function composeUntrustedHtmlDocument(html: string): string;
|
|
47
|
+
export interface UntrustedHtmlContentProps {
|
|
48
|
+
/** HTML from outside the application. Never trusted, never injected into the page. */
|
|
49
|
+
value: string;
|
|
50
|
+
/** Accessible name of the frame (a title the screen reader announces). */
|
|
51
|
+
title: string;
|
|
52
|
+
className?: string;
|
|
53
|
+
}
|
|
54
|
+
export declare function UntrustedHtmlContent({ value, title, className }: UntrustedHtmlContentProps): React.JSX.Element;
|
|
55
|
+
//# sourceMappingURL=untrusted-html-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"untrusted-html-content.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/untrusted-html-content.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B;;;GAGG;AACH,eAAO,MAAM,sCAAsC,iFAAiF,CAAA;AAEpI,gGAAgG;AAChG,eAAO,MAAM,sBAAsB,gDAAgD,CAAA;AAEnF,2FAA2F;AAC3F,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWjE;AAED,MAAM,WAAW,yBAAyB;IACxC,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,yBAAyB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAY9G"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* UntrustedHtmlContent — renders HTML a STRANGER wrote (the HTML part of a received email, #1600) without letting it
|
|
5
|
+
* run, reach the network, or restyle the application (#1912).
|
|
6
|
+
*
|
|
7
|
+
* ## What a mail client does, and what this does
|
|
8
|
+
*
|
|
9
|
+
* Every mainstream mail client refuses remote content in received mail by default: Thunderbird blocks it and shows a
|
|
10
|
+
* "remote content" bar, Apple Mail's Mail Privacy Protection and Gmail's image proxy exist because a remote image is
|
|
11
|
+
* a read receipt (it tells the sender WHEN the message was opened and FROM WHICH address). Browser-based clients do it
|
|
12
|
+
* by rendering the message in a sandboxed frame with a content-security policy that allows no fetch at all. This does
|
|
13
|
+
* the same, with the browser as the enforcer rather than a rewrite pass:
|
|
14
|
+
*
|
|
15
|
+
* - `<iframe sandbox>` WITHOUT `allow-scripts` and WITHOUT `allow-same-origin`: nothing in the message executes, and
|
|
16
|
+
* the frame is an opaque origin that can read neither the application's DOM, cookies nor storage;
|
|
17
|
+
* - a CSP meta as the frame's first element — `default-src 'none'`: no image, stylesheet, font, media or frame is
|
|
18
|
+
* fetched from anywhere. Only inline `data:` images and inline `<style>` are allowed;
|
|
19
|
+
* - `<base target="_blank">` with `allow-popups` / `allow-popups-to-escape-sandbox`: a link the reader CLICKS opens in a
|
|
20
|
+
* new tab (a reader's own act, not the message's); a form never submits (no `allow-forms`).
|
|
21
|
+
*
|
|
22
|
+
* spec-cite: HTML Living Standard §4.8.5 "The iframe element" — the `sandbox` attribute's flags (`allow-scripts`,
|
|
23
|
+
* `allow-same-origin`, `allow-popups`, `allow-popups-to-escape-sandbox`, `allow-forms`) and the opaque origin a frame
|
|
24
|
+
* without `allow-same-origin` receives. https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox
|
|
25
|
+
*
|
|
26
|
+
* ## Rejected: sanitizing into the page (drop `<style>`, strip remote `src`)
|
|
27
|
+
*
|
|
28
|
+
* The first reading surface ran the HTML through the markdown pipeline's `rehype-sanitize`, which keeps images and
|
|
29
|
+
* UNWRAPS a `<style>` element into visible text. Tightening that schema (drop `<style>`, strip every remote `src`,
|
|
30
|
+
* `srcset`, `background` and CSS `url()`) was considered and rejected: it is a hand-kept list of ways HTML reaches the
|
|
31
|
+
* network, and it would still inject the message's markup into the application's own DOM, where a missed
|
|
32
|
+
* vector is a leak and a `position: fixed` rule is a clickjacking overlay. The frame makes the browser enforce
|
|
33
|
+
* "no fetch" for every vector at once, and scopes the message's styles to itself — which is why they are KEPT rather
|
|
34
|
+
* than dropped: a styled newsletter stays readable and cannot touch the page around it.
|
|
35
|
+
*
|
|
36
|
+
* Remote content has no opt-in here. Blocking it always is the stricter half of what mail clients do; an explicit
|
|
37
|
+
* "load remote content" action would be a separate, deliberate addition.
|
|
38
|
+
*/
|
|
39
|
+
import * as React from "react";
|
|
40
|
+
import { cn } from "@wildo-ai/saas-frontend-lib";
|
|
41
|
+
/**
|
|
42
|
+
* The frame's policy. `img-src data:` keeps inline images a message carries in its own body; nothing else loads.
|
|
43
|
+
* `style-src 'unsafe-inline'` lets the message's own `<style>` apply INSIDE the frame only.
|
|
44
|
+
*/
|
|
45
|
+
export const UNTRUSTED_HTML_CONTENT_SECURITY_POLICY = "default-src 'none'; img-src data:; style-src 'unsafe-inline'; font-src data:";
|
|
46
|
+
/** The sandbox flags: links a reader clicks may open a new tab, and nothing else is granted. */
|
|
47
|
+
export const UNTRUSTED_HTML_SANDBOX = "allow-popups allow-popups-to-escape-sandbox";
|
|
48
|
+
/** The document the frame renders: the policy FIRST, so it governs everything after it. */
|
|
49
|
+
export function composeUntrustedHtmlDocument(html) {
|
|
50
|
+
return [
|
|
51
|
+
"<!doctype html><html><head>",
|
|
52
|
+
`<meta http-equiv="Content-Security-Policy" content="${UNTRUSTED_HTML_CONTENT_SECURITY_POLICY}">`,
|
|
53
|
+
'<meta name="referrer" content="no-referrer">',
|
|
54
|
+
'<base target="_blank">',
|
|
55
|
+
"<style>body{margin:0;font-family:system-ui,sans-serif;font-size:14px;line-height:1.5;word-wrap:break-word}img{max-width:100%;height:auto}</style>",
|
|
56
|
+
"</head><body>",
|
|
57
|
+
html,
|
|
58
|
+
"</body></html>",
|
|
59
|
+
].join("");
|
|
60
|
+
}
|
|
61
|
+
export function UntrustedHtmlContent({ value, title, className }) {
|
|
62
|
+
const document = React.useMemo(() => composeUntrustedHtmlDocument(value), [value]);
|
|
63
|
+
return (_jsx("iframe", { title: title, sandbox: UNTRUSTED_HTML_SANDBOX, srcDoc: document, referrerPolicy: "no-referrer",
|
|
64
|
+
// An opaque-origin frame cannot be measured from outside, so it has a reading height and resizes by hand.
|
|
65
|
+
className: cn("w-full min-h-[12rem] h-[32rem] resize-y rounded-md border border-border bg-background", className) }));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=untrusted-html-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"untrusted-html-content.js","sourceRoot":"","sources":["../../../../../src/components/data-display/untrusted-html-content.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAA;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,8EAA8E,CAAA;AAEpI,gGAAgG;AAChG,MAAM,CAAC,MAAM,sBAAsB,GAAG,6CAA6C,CAAA;AAEnF,2FAA2F;AAC3F,MAAM,UAAU,4BAA4B,CAAC,IAAY;IACvD,OAAO;QACL,6BAA6B;QAC7B,uDAAuD,sCAAsC,IAAI;QACjG,8CAA8C;QAC9C,wBAAwB;QACxB,mJAAmJ;QACnJ,eAAe;QACf,IAAI;QACJ,gBAAgB;KACjB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACZ,CAAC;AAUD,MAAM,UAAU,oBAAoB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAA6B;IACzF,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAClF,OAAO,CACL,iBACE,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,QAAQ,EAChB,cAAc,EAAC,aAAa;QAC5B,0GAA0G;QAC1G,SAAS,EAAE,EAAE,CAAC,uFAAuF,EAAE,SAAS,CAAC,GACjH,CACH,CAAA;AACH,CAAC","sourcesContent":["\"use client\"\n\n/**\n * UntrustedHtmlContent — renders HTML a STRANGER wrote (the HTML part of a received email, #1600) without letting it\n * run, reach the network, or restyle the application (#1912).\n *\n * ## What a mail client does, and what this does\n *\n * Every mainstream mail client refuses remote content in received mail by default: Thunderbird blocks it and shows a\n * \"remote content\" bar, Apple Mail's Mail Privacy Protection and Gmail's image proxy exist because a remote image is\n * a read receipt (it tells the sender WHEN the message was opened and FROM WHICH address). Browser-based clients do it\n * by rendering the message in a sandboxed frame with a content-security policy that allows no fetch at all. This does\n * the same, with the browser as the enforcer rather than a rewrite pass:\n *\n * - `<iframe sandbox>` WITHOUT `allow-scripts` and WITHOUT `allow-same-origin`: nothing in the message executes, and\n * the frame is an opaque origin that can read neither the application's DOM, cookies nor storage;\n * - a CSP meta as the frame's first element — `default-src 'none'`: no image, stylesheet, font, media or frame is\n * fetched from anywhere. Only inline `data:` images and inline `<style>` are allowed;\n * - `<base target=\"_blank\">` with `allow-popups` / `allow-popups-to-escape-sandbox`: a link the reader CLICKS opens in a\n * new tab (a reader's own act, not the message's); a form never submits (no `allow-forms`).\n *\n * spec-cite: HTML Living Standard §4.8.5 \"The iframe element\" — the `sandbox` attribute's flags (`allow-scripts`,\n * `allow-same-origin`, `allow-popups`, `allow-popups-to-escape-sandbox`, `allow-forms`) and the opaque origin a frame\n * without `allow-same-origin` receives. https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox\n *\n * ## Rejected: sanitizing into the page (drop `<style>`, strip remote `src`)\n *\n * The first reading surface ran the HTML through the markdown pipeline's `rehype-sanitize`, which keeps images and\n * UNWRAPS a `<style>` element into visible text. Tightening that schema (drop `<style>`, strip every remote `src`,\n * `srcset`, `background` and CSS `url()`) was considered and rejected: it is a hand-kept list of ways HTML reaches the\n * network, and it would still inject the message's markup into the application's own DOM, where a missed\n * vector is a leak and a `position: fixed` rule is a clickjacking overlay. The frame makes the browser enforce\n * \"no fetch\" for every vector at once, and scopes the message's styles to itself — which is why they are KEPT rather\n * than dropped: a styled newsletter stays readable and cannot touch the page around it.\n *\n * Remote content has no opt-in here. Blocking it always is the stricter half of what mail clients do; an explicit\n * \"load remote content\" action would be a separate, deliberate addition.\n */\n\nimport * as React from \"react\"\n\nimport { cn } from \"@wildo-ai/saas-frontend-lib\"\n\n/**\n * The frame's policy. `img-src data:` keeps inline images a message carries in its own body; nothing else loads.\n * `style-src 'unsafe-inline'` lets the message's own `<style>` apply INSIDE the frame only.\n */\nexport const UNTRUSTED_HTML_CONTENT_SECURITY_POLICY = \"default-src 'none'; img-src data:; style-src 'unsafe-inline'; font-src data:\"\n\n/** The sandbox flags: links a reader clicks may open a new tab, and nothing else is granted. */\nexport const UNTRUSTED_HTML_SANDBOX = \"allow-popups allow-popups-to-escape-sandbox\"\n\n/** The document the frame renders: the policy FIRST, so it governs everything after it. */\nexport function composeUntrustedHtmlDocument(html: string): string {\n return [\n \"<!doctype html><html><head>\",\n `<meta http-equiv=\"Content-Security-Policy\" content=\"${UNTRUSTED_HTML_CONTENT_SECURITY_POLICY}\">`,\n '<meta name=\"referrer\" content=\"no-referrer\">',\n '<base target=\"_blank\">',\n \"<style>body{margin:0;font-family:system-ui,sans-serif;font-size:14px;line-height:1.5;word-wrap:break-word}img{max-width:100%;height:auto}</style>\",\n \"</head><body>\",\n html,\n \"</body></html>\",\n ].join(\"\")\n}\n\nexport interface UntrustedHtmlContentProps {\n /** HTML from outside the application. Never trusted, never injected into the page. */\n value: string\n /** Accessible name of the frame (a title the screen reader announces). */\n title: string\n className?: string\n}\n\nexport function UntrustedHtmlContent({ value, title, className }: UntrustedHtmlContentProps): React.JSX.Element {\n const document = React.useMemo(() => composeUntrustedHtmlDocument(value), [value])\n return (\n <iframe\n title={title}\n sandbox={UNTRUSTED_HTML_SANDBOX}\n srcDoc={document}\n referrerPolicy=\"no-referrer\"\n // An opaque-origin frame cannot be measured from outside, so it has a reading height and resizes by hand.\n className={cn(\"w-full min-h-[12rem] h-[32rem] resize-y rounded-md border border-border bg-background\", className)}\n />\n )\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-primitive.labels.d.ts","sourceRoot":"","sources":["../../../../../../src/components/form/chromes/form-primitive.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,mBAAmB,EAA2B,MAAM,qCAAqC,CAAC;AAM1I,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,EAAO,CAAC;AAG5D,eAAO,MAAM,yBAAyB,EAAE,mBAAmB,EAAO,CAAC;AAGnE,eAAO,MAAM,6BAA6B,EAAE,mBAAmB,EAAO,CAAC;AAGvE,eAAO,MAAM,uBAAuB,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"form-primitive.labels.d.ts","sourceRoot":"","sources":["../../../../../../src/components/form/chromes/form-primitive.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,mBAAmB,EAA2B,MAAM,qCAAqC,CAAC;AAM1I,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,EAAO,CAAC;AAG5D,eAAO,MAAM,yBAAyB,EAAE,mBAAmB,EAAO,CAAC;AAGnE,eAAO,MAAM,6BAA6B,EAAE,mBAAmB,EAAO,CAAC;AAGvE,eAAO,MAAM,uBAAuB,EAAE,mBAAmB,EA+FxD,CAAC;AAGF,eAAO,MAAM,sBAAsB,EAAE,mBAAmB,EAAO,CAAC;AAGhE,eAAO,MAAM,uBAAuB,EAAE,mBAAmB,EAAO,CAAC;AAGjE,eAAO,MAAM,yBAAyB,EAAE,mBAAmB,EAgI1D,CAAC"}
|
|
@@ -89,6 +89,15 @@ export const LowLevelFormFieldLabels = [
|
|
|
89
89
|
kind: LabelKind.MESSAGE,
|
|
90
90
|
purpose: 'Shown when an inline relationship edit cannot be saved because the save route is unavailable — distinct from a save that was attempted and failed',
|
|
91
91
|
},
|
|
92
|
+
{
|
|
93
|
+
ref: 'syncedFromAsOf',
|
|
94
|
+
kind: LabelKind.MESSAGE,
|
|
95
|
+
purpose: 'A short note beneath a read-only value that this application copies from another business system (an ERP such as Odoo or SAP) rather than holding itself: it names that system and says how current the local copy is — the time the last completed synchronisation started. It tells the reader the value is edited in that other system, not here',
|
|
96
|
+
params: [
|
|
97
|
+
{ key: 'system', meaning: "the name of the other system the value was copied from, already in the reader's words (for example \"Odoo\")" },
|
|
98
|
+
{ key: 'asOf', meaning: 'when the copy was last brought up to date, already formatted — either relative ("12 minutes ago") or a date and time' },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
92
101
|
{
|
|
93
102
|
ref: 'unsupportedDisplayType',
|
|
94
103
|
kind: LabelKind.MESSAGE,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-primitive.labels.js","sourceRoot":"","sources":["../../../../../../src/components/form/chromes/form-primitive.labels.ts"],"names":[],"mappings":"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","sourcesContent":["import { FrontendComponentType, LabelKind, type LabellingUnitaryDef, registerComponentLabels } from '@wildo-ai/presets-components-models';\n\n// Companion-only label metadata for this component: keys + params + (where\n// authored) per-key purpose / kind / variable meaning. Statically scanned by\n// the dev companion; NOT imported at runtime, so it never ships in the bundle.\n\nexport const LowLevelFormLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM, LowLevelFormLabels);\n\nexport const LowLevelFormControlLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_CONTROL, LowLevelFormControlLabels);\n\nexport const LowLevelFormDescriptionLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_DESCRIPTION, LowLevelFormDescriptionLabels);\n\nexport const LowLevelFormFieldLabels: LabellingUnitaryDef[] = [\n // Autosave / inline-edit save states\n { ref: 'saving', kind: LabelKind.LABEL, purpose: 'Status shown while a field value is being persisted' },\n { ref: 'saved', kind: LabelKind.LABEL, purpose: 'Confirmation shown once a field value has persisted successfully' },\n { ref: 'retry', kind: LabelKind.BUTTON, purpose: 'Button that re-attempts a failed field save' },\n { ref: 'save_failed', kind: LabelKind.MESSAGE, purpose: 'Error shown when persisting a field value fails' },\n { ref: 'field_reset_after_conflict', kind: LabelKind.MESSAGE, purpose: 'Shown on an inline-edited field after someone else saved it first: the edit was discarded and the field now shows the latest saved value' },\n {\n ref: 'save_conflict',\n kind: LabelKind.MESSAGE,\n purpose: 'Error shown when a field save is rejected because the record changed since it was loaded',\n },\n // Shared display labels (read-only value rendering)\n { ref: 'noValue', kind: LabelKind.EMPTY_STATE, purpose: 'Placeholder shown in place of a field that has no value' },\n // The other two halves of `DisplayEmptyReason`. One em dash used to say all three things at once:\n // a field awaiting the operator's input, a list with no members, and a computed value nothing has\n // produced yet. `noValue` above keeps the NOT_SET case and its existing words.\n { ref: 'noValueNone', kind: LabelKind.EMPTY_STATE, purpose: 'Shown in place of a COLLECTION (list, object or record) that exists but has no members yet — frequently the correct state rather than a gap, so the words should read as a calm statement (\"None yet\"), not as something missing' },\n { ref: 'noValueNotProvided', kind: LabelKind.EMPTY_STATE, purpose: 'Shown in place of a COMPUTED or system-owned field that has no value — the reader cannot set it, so the words must NOT invite input; they say nothing has produced one yet (\"Not available\")' },\n { ref: 'clear', kind: LabelKind.ARIA, purpose: 'Accessible name of the affordance inside a clearable picker that removes the current selection, returning the control to its empty state' },\n { ref: 'displayError', kind: LabelKind.MESSAGE, purpose: 'Fallback text when a field value cannot be rendered' },\n { ref: 'object', kind: LabelKind.ARIA, purpose: 'Accessible name for a rendered object/record value region' },\n {\n ref: 'resourceLinkLimitReached',\n kind: LabelKind.MESSAGE,\n purpose: 'Notice shown where an automatic display stops expanding LINKED RECORDS, having already followed the maximum number of resource links. It never appears over a record\\'s own nested fields, which are always rendered in full',\n },\n { ref: 'list', kind: LabelKind.ARIA, purpose: 'Accessible name for a rendered list/array value region' },\n {\n ref: 'showMore',\n kind: LabelKind.BUTTON,\n purpose: 'Reveals list or object entries hidden behind a truncation cutoff',\n params: [{ key: 'count', meaning: 'number of additional entries that are currently hidden' }],\n },\n {\n ref: 'editField',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the inline-edit affordance on a displayed field',\n params: [{ key: 'label', meaning: 'display name of the field being edited' }],\n },\n { ref: 'clearSelection', kind: LabelKind.BUTTON, purpose: 'Clears the chosen value of a relationship/reference field' },\n // Select / Combobox shared labels\n {\n ref: 'selectPlaceholder',\n kind: LabelKind.PLACEHOLDER,\n purpose: 'Prompt shown in a select/combobox trigger before a choice is made',\n },\n {\n ref: 'searchPlaceholder',\n kind: LabelKind.PLACEHOLDER,\n purpose: 'Prompt shown in the filter input of a searchable select/combobox',\n },\n { ref: 'noResults', kind: LabelKind.EMPTY_STATE, purpose: 'Shown when a select/combobox search matches no options' },\n // Multi-select labels\n {\n ref: 'selectedCount',\n kind: LabelKind.LABEL,\n purpose: 'Multi-select trigger summary counting how many options are chosen',\n params: [{ key: 'count', meaning: 'number of options currently selected' }],\n },\n { ref: 'clearAll', kind: LabelKind.BUTTON, purpose: 'Deselects every option in a multi-select' },\n { ref: 'selectAll', kind: LabelKind.BUTTON, purpose: 'Selects every available option in a multi-select' },\n // Chrome labels\n { ref: 'moreInformation', kind: LabelKind.ARIA, purpose: \"Accessible label for a field's help/info trigger\" },\n // Display-side labels. These four were READ by components and declared NOWHERE until 2026-09-18,\n // which is the drift direction this file's own header warns about: \"a key the component reads and\n // this array omits renders as its RAW KEY PATH in the browser — visible only to somebody looking\n // at the panel\". `unsupportedDisplayType` is how it was caught — it rendered verbatim on five\n // settings panes, and reading WHY led to a whole missing display branch (`FieldSchemaType.RECORD`).\n {\n ref: 'fileCount',\n kind: LabelKind.LABEL,\n purpose: 'Summary of how many files a file field holds, shown instead of listing them',\n params: [{ key: 'count', meaning: 'number of files attached to the field' }],\n },\n { ref: 'noFile', kind: LabelKind.EMPTY_STATE, purpose: 'Shown in place of a file field that holds no file' },\n {\n ref: 'save_unavailable',\n kind: LabelKind.MESSAGE,\n purpose: 'Shown when an inline relationship edit cannot be saved because the save route is unavailable — distinct from a save that was attempted and failed',\n },\n {\n ref: 'unsupportedDisplayType',\n kind: LabelKind.MESSAGE,\n purpose: 'Shown beside the raw schema type when a field\\'s type has no display renderer at all; it names a framework gap rather than anything the reader can act on, so it reads as a diagnostic and not as user error',\n },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_FIELD, LowLevelFormFieldLabels);\n\nexport const LowLevelFormItemLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_ITEM, LowLevelFormItemLabels);\n\nexport const LowLevelFormLabelLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_LABEL, LowLevelFormLabelLabels);\n\nexport const LowLevelFormMessageLabels: LabellingUnitaryDef[] = [\n // Error summary headings\n {\n ref: 'serverValidationTitle',\n kind: LabelKind.HEADING,\n purpose: 'Heading above validation errors returned by the server',\n },\n { ref: 'formErrorsTitle', kind: LabelKind.HEADING, purpose: 'Heading above the aggregated form-error summary' },\n {\n ref: 'moreErrors',\n kind: LabelKind.LABEL,\n purpose: 'Overflow line counting validation errors not listed in the summary',\n params: [{ key: 'count', meaning: 'number of additional errors beyond those shown' }],\n },\n // Wizard navigation\n { ref: 'wizardNext', kind: LabelKind.BUTTON, purpose: 'Advances to the next step of a multi-step form' },\n { ref: 'wizardPrevious', kind: LabelKind.BUTTON, purpose: 'Returns to the previous step of a multi-step form' },\n { ref: 'wizardSubmit', kind: LabelKind.BUTTON, purpose: 'Submits the form from the final wizard step' },\n {\n ref: 'wizardStepDefault',\n kind: LabelKind.LABEL,\n purpose: 'Fallback name for a wizard step that has no authored title',\n params: [{ key: 'index', meaning: \"the step's 1-based position in the wizard\" }],\n },\n // Section save\n { ref: 'sectionSave', kind: LabelKind.BUTTON, purpose: 'Saves the values of a single form section' },\n { ref: 'sectionSaving', kind: LabelKind.LABEL, purpose: 'Status shown while a form section is being saved' },\n // Default submit action (skeleton SubmitButton fallback when no label prop)\n { ref: 'submitSave', kind: LabelKind.BUTTON, purpose: 'Default submit-button text when the form supplies no custom label' },\n // Array field messages\n { ref: 'arrayAddItem', kind: LabelKind.BUTTON, purpose: 'Adds a new entry to a repeatable array field' },\n { ref: 'arrayItemLabel', kind: LabelKind.LABEL, purpose: 'Base name given to each entry of an array field' },\n { ref: 'arrayEmptyMessage', kind: LabelKind.EMPTY_STATE, purpose: 'Shown when an array field has no entries yet' },\n {\n ref: 'arrayDragHandle',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the drag handle that reorders an array entry',\n params: [{ key: 'label', meaning: 'name of the array entry being dragged' }],\n },\n {\n ref: 'arrayMoveUp',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the button that moves an array entry earlier',\n params: [{ key: 'label', meaning: 'name of the array entry being moved' }],\n },\n {\n ref: 'arrayMoveDown',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the button that moves an array entry later',\n params: [{ key: 'label', meaning: 'name of the array entry being moved' }],\n },\n {\n ref: 'arrayRemoveItem',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the button that deletes an array entry',\n params: [{ key: 'label', meaning: 'name of the array entry being removed' }],\n },\n // Checkbox group constraint hints\n {\n ref: 'checkboxSelectExactly',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group requires an exact number of selections',\n params: [{ key: 'count', meaning: 'exact number of options that must be checked' }],\n },\n {\n ref: 'checkboxSelectAtLeast',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group requires a minimum number of selections',\n params: [{ key: 'count', meaning: 'minimum number of options that must be checked' }],\n },\n {\n ref: 'checkboxSelectUpTo',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group allows at most a given number of selections',\n params: [{ key: 'count', meaning: 'maximum number of options that may be checked' }],\n },\n {\n ref: 'checkboxSelectRange',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group requires a number of selections within a range',\n params: [\n { key: 'min', meaning: 'minimum number of options that must be checked' },\n { key: 'max', meaning: 'maximum number of options that may be checked' },\n ],\n },\n {\n ref: 'checkboxSelectedCount',\n kind: LabelKind.LABEL,\n purpose: 'Live count of how many options are checked in a checkbox group',\n params: [{ key: 'count', meaning: 'number of options currently checked' }],\n },\n // Record/Map field messages\n { ref: 'recordAddEntry', kind: LabelKind.BUTTON, purpose: 'Adds a new key/value pair to a record/map field' },\n { ref: 'recordKeyLabel', kind: LabelKind.LABEL, purpose: 'Label for the key input of a record/map entry' },\n { ref: 'recordValueLabel', kind: LabelKind.LABEL, purpose: 'Label for the value input of a record/map entry' },\n { ref: 'recordEmptyMessage', kind: LabelKind.EMPTY_STATE, purpose: 'Shown when a record/map field has no entries yet' },\n {\n ref: 'recordDuplicateKey',\n kind: LabelKind.MESSAGE,\n purpose: 'Error shown when a record/map entry reuses an existing key',\n },\n {\n ref: 'recordEnterKeyFirst',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a record/map entry needs a key before a value can be set',\n },\n // Range field messages\n {\n ref: 'rangeFromMustBeLessThanTo',\n kind: LabelKind.MESSAGE,\n purpose: \"Error shown when a range field's start exceeds its end\",\n },\n // Uniqueness pre-validation messages\n {\n ref: 'uniqueFieldChecking',\n kind: LabelKind.MESSAGE,\n purpose: \"Status shown while a field's value is being checked for uniqueness\",\n },\n {\n ref: 'uniqueFieldConflict',\n kind: LabelKind.MESSAGE,\n purpose: 'Error shown when a unique field value is already taken',\n },\n {\n ref: 'uniqueFieldAvailable',\n kind: LabelKind.MESSAGE,\n purpose: 'Confirmation that a unique field value is available',\n },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_MESSAGE, LowLevelFormMessageLabels);\n"]}
|
|
1
|
+
{"version":3,"file":"form-primitive.labels.js","sourceRoot":"","sources":["../../../../../../src/components/form/chromes/form-primitive.labels.ts"],"names":[],"mappings":"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","sourcesContent":["import { FrontendComponentType, LabelKind, type LabellingUnitaryDef, registerComponentLabels } from '@wildo-ai/presets-components-models';\n\n// Companion-only label metadata for this component: keys + params + (where\n// authored) per-key purpose / kind / variable meaning. Statically scanned by\n// the dev companion; NOT imported at runtime, so it never ships in the bundle.\n\nexport const LowLevelFormLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM, LowLevelFormLabels);\n\nexport const LowLevelFormControlLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_CONTROL, LowLevelFormControlLabels);\n\nexport const LowLevelFormDescriptionLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_DESCRIPTION, LowLevelFormDescriptionLabels);\n\nexport const LowLevelFormFieldLabels: LabellingUnitaryDef[] = [\n // Autosave / inline-edit save states\n { ref: 'saving', kind: LabelKind.LABEL, purpose: 'Status shown while a field value is being persisted' },\n { ref: 'saved', kind: LabelKind.LABEL, purpose: 'Confirmation shown once a field value has persisted successfully' },\n { ref: 'retry', kind: LabelKind.BUTTON, purpose: 'Button that re-attempts a failed field save' },\n { ref: 'save_failed', kind: LabelKind.MESSAGE, purpose: 'Error shown when persisting a field value fails' },\n { ref: 'field_reset_after_conflict', kind: LabelKind.MESSAGE, purpose: 'Shown on an inline-edited field after someone else saved it first: the edit was discarded and the field now shows the latest saved value' },\n {\n ref: 'save_conflict',\n kind: LabelKind.MESSAGE,\n purpose: 'Error shown when a field save is rejected because the record changed since it was loaded',\n },\n // Shared display labels (read-only value rendering)\n { ref: 'noValue', kind: LabelKind.EMPTY_STATE, purpose: 'Placeholder shown in place of a field that has no value' },\n // The other two halves of `DisplayEmptyReason`. One em dash used to say all three things at once:\n // a field awaiting the operator's input, a list with no members, and a computed value nothing has\n // produced yet. `noValue` above keeps the NOT_SET case and its existing words.\n { ref: 'noValueNone', kind: LabelKind.EMPTY_STATE, purpose: 'Shown in place of a COLLECTION (list, object or record) that exists but has no members yet — frequently the correct state rather than a gap, so the words should read as a calm statement (\"None yet\"), not as something missing' },\n { ref: 'noValueNotProvided', kind: LabelKind.EMPTY_STATE, purpose: 'Shown in place of a COMPUTED or system-owned field that has no value — the reader cannot set it, so the words must NOT invite input; they say nothing has produced one yet (\"Not available\")' },\n { ref: 'clear', kind: LabelKind.ARIA, purpose: 'Accessible name of the affordance inside a clearable picker that removes the current selection, returning the control to its empty state' },\n { ref: 'displayError', kind: LabelKind.MESSAGE, purpose: 'Fallback text when a field value cannot be rendered' },\n { ref: 'object', kind: LabelKind.ARIA, purpose: 'Accessible name for a rendered object/record value region' },\n {\n ref: 'resourceLinkLimitReached',\n kind: LabelKind.MESSAGE,\n purpose: 'Notice shown where an automatic display stops expanding LINKED RECORDS, having already followed the maximum number of resource links. It never appears over a record\\'s own nested fields, which are always rendered in full',\n },\n { ref: 'list', kind: LabelKind.ARIA, purpose: 'Accessible name for a rendered list/array value region' },\n {\n ref: 'showMore',\n kind: LabelKind.BUTTON,\n purpose: 'Reveals list or object entries hidden behind a truncation cutoff',\n params: [{ key: 'count', meaning: 'number of additional entries that are currently hidden' }],\n },\n {\n ref: 'editField',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the inline-edit affordance on a displayed field',\n params: [{ key: 'label', meaning: 'display name of the field being edited' }],\n },\n { ref: 'clearSelection', kind: LabelKind.BUTTON, purpose: 'Clears the chosen value of a relationship/reference field' },\n // Select / Combobox shared labels\n {\n ref: 'selectPlaceholder',\n kind: LabelKind.PLACEHOLDER,\n purpose: 'Prompt shown in a select/combobox trigger before a choice is made',\n },\n {\n ref: 'searchPlaceholder',\n kind: LabelKind.PLACEHOLDER,\n purpose: 'Prompt shown in the filter input of a searchable select/combobox',\n },\n { ref: 'noResults', kind: LabelKind.EMPTY_STATE, purpose: 'Shown when a select/combobox search matches no options' },\n // Multi-select labels\n {\n ref: 'selectedCount',\n kind: LabelKind.LABEL,\n purpose: 'Multi-select trigger summary counting how many options are chosen',\n params: [{ key: 'count', meaning: 'number of options currently selected' }],\n },\n { ref: 'clearAll', kind: LabelKind.BUTTON, purpose: 'Deselects every option in a multi-select' },\n { ref: 'selectAll', kind: LabelKind.BUTTON, purpose: 'Selects every available option in a multi-select' },\n // Chrome labels\n { ref: 'moreInformation', kind: LabelKind.ARIA, purpose: \"Accessible label for a field's help/info trigger\" },\n // Display-side labels. These four were READ by components and declared NOWHERE until 2026-09-18,\n // which is the drift direction this file's own header warns about: \"a key the component reads and\n // this array omits renders as its RAW KEY PATH in the browser — visible only to somebody looking\n // at the panel\". `unsupportedDisplayType` is how it was caught — it rendered verbatim on five\n // settings panes, and reading WHY led to a whole missing display branch (`FieldSchemaType.RECORD`).\n {\n ref: 'fileCount',\n kind: LabelKind.LABEL,\n purpose: 'Summary of how many files a file field holds, shown instead of listing them',\n params: [{ key: 'count', meaning: 'number of files attached to the field' }],\n },\n { ref: 'noFile', kind: LabelKind.EMPTY_STATE, purpose: 'Shown in place of a file field that holds no file' },\n {\n ref: 'save_unavailable',\n kind: LabelKind.MESSAGE,\n purpose: 'Shown when an inline relationship edit cannot be saved because the save route is unavailable — distinct from a save that was attempted and failed',\n },\n {\n ref: 'syncedFromAsOf',\n kind: LabelKind.MESSAGE,\n purpose: 'A short note beneath a read-only value that this application copies from another business system (an ERP such as Odoo or SAP) rather than holding itself: it names that system and says how current the local copy is — the time the last completed synchronisation started. It tells the reader the value is edited in that other system, not here',\n params: [\n { key: 'system', meaning: \"the name of the other system the value was copied from, already in the reader's words (for example \\\"Odoo\\\")\" },\n { key: 'asOf', meaning: 'when the copy was last brought up to date, already formatted — either relative (\"12 minutes ago\") or a date and time' },\n ],\n },\n {\n ref: 'unsupportedDisplayType',\n kind: LabelKind.MESSAGE,\n purpose: 'Shown beside the raw schema type when a field\\'s type has no display renderer at all; it names a framework gap rather than anything the reader can act on, so it reads as a diagnostic and not as user error',\n },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_FIELD, LowLevelFormFieldLabels);\n\nexport const LowLevelFormItemLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_ITEM, LowLevelFormItemLabels);\n\nexport const LowLevelFormLabelLabels: LabellingUnitaryDef[] = [];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_LABEL, LowLevelFormLabelLabels);\n\nexport const LowLevelFormMessageLabels: LabellingUnitaryDef[] = [\n // Error summary headings\n {\n ref: 'serverValidationTitle',\n kind: LabelKind.HEADING,\n purpose: 'Heading above validation errors returned by the server',\n },\n { ref: 'formErrorsTitle', kind: LabelKind.HEADING, purpose: 'Heading above the aggregated form-error summary' },\n {\n ref: 'moreErrors',\n kind: LabelKind.LABEL,\n purpose: 'Overflow line counting validation errors not listed in the summary',\n params: [{ key: 'count', meaning: 'number of additional errors beyond those shown' }],\n },\n // Wizard navigation\n { ref: 'wizardNext', kind: LabelKind.BUTTON, purpose: 'Advances to the next step of a multi-step form' },\n { ref: 'wizardPrevious', kind: LabelKind.BUTTON, purpose: 'Returns to the previous step of a multi-step form' },\n { ref: 'wizardSubmit', kind: LabelKind.BUTTON, purpose: 'Submits the form from the final wizard step' },\n {\n ref: 'wizardStepDefault',\n kind: LabelKind.LABEL,\n purpose: 'Fallback name for a wizard step that has no authored title',\n params: [{ key: 'index', meaning: \"the step's 1-based position in the wizard\" }],\n },\n // Section save\n { ref: 'sectionSave', kind: LabelKind.BUTTON, purpose: 'Saves the values of a single form section' },\n { ref: 'sectionSaving', kind: LabelKind.LABEL, purpose: 'Status shown while a form section is being saved' },\n // Default submit action (skeleton SubmitButton fallback when no label prop)\n { ref: 'submitSave', kind: LabelKind.BUTTON, purpose: 'Default submit-button text when the form supplies no custom label' },\n // Array field messages\n { ref: 'arrayAddItem', kind: LabelKind.BUTTON, purpose: 'Adds a new entry to a repeatable array field' },\n { ref: 'arrayItemLabel', kind: LabelKind.LABEL, purpose: 'Base name given to each entry of an array field' },\n { ref: 'arrayEmptyMessage', kind: LabelKind.EMPTY_STATE, purpose: 'Shown when an array field has no entries yet' },\n {\n ref: 'arrayDragHandle',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the drag handle that reorders an array entry',\n params: [{ key: 'label', meaning: 'name of the array entry being dragged' }],\n },\n {\n ref: 'arrayMoveUp',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the button that moves an array entry earlier',\n params: [{ key: 'label', meaning: 'name of the array entry being moved' }],\n },\n {\n ref: 'arrayMoveDown',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the button that moves an array entry later',\n params: [{ key: 'label', meaning: 'name of the array entry being moved' }],\n },\n {\n ref: 'arrayRemoveItem',\n kind: LabelKind.ARIA,\n purpose: 'Accessible label for the button that deletes an array entry',\n params: [{ key: 'label', meaning: 'name of the array entry being removed' }],\n },\n // Checkbox group constraint hints\n {\n ref: 'checkboxSelectExactly',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group requires an exact number of selections',\n params: [{ key: 'count', meaning: 'exact number of options that must be checked' }],\n },\n {\n ref: 'checkboxSelectAtLeast',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group requires a minimum number of selections',\n params: [{ key: 'count', meaning: 'minimum number of options that must be checked' }],\n },\n {\n ref: 'checkboxSelectUpTo',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group allows at most a given number of selections',\n params: [{ key: 'count', meaning: 'maximum number of options that may be checked' }],\n },\n {\n ref: 'checkboxSelectRange',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a checkbox group requires a number of selections within a range',\n params: [\n { key: 'min', meaning: 'minimum number of options that must be checked' },\n { key: 'max', meaning: 'maximum number of options that may be checked' },\n ],\n },\n {\n ref: 'checkboxSelectedCount',\n kind: LabelKind.LABEL,\n purpose: 'Live count of how many options are checked in a checkbox group',\n params: [{ key: 'count', meaning: 'number of options currently checked' }],\n },\n // Record/Map field messages\n { ref: 'recordAddEntry', kind: LabelKind.BUTTON, purpose: 'Adds a new key/value pair to a record/map field' },\n { ref: 'recordKeyLabel', kind: LabelKind.LABEL, purpose: 'Label for the key input of a record/map entry' },\n { ref: 'recordValueLabel', kind: LabelKind.LABEL, purpose: 'Label for the value input of a record/map entry' },\n { ref: 'recordEmptyMessage', kind: LabelKind.EMPTY_STATE, purpose: 'Shown when a record/map field has no entries yet' },\n {\n ref: 'recordDuplicateKey',\n kind: LabelKind.MESSAGE,\n purpose: 'Error shown when a record/map entry reuses an existing key',\n },\n {\n ref: 'recordEnterKeyFirst',\n kind: LabelKind.MESSAGE,\n purpose: 'Hint that a record/map entry needs a key before a value can be set',\n },\n // Range field messages\n {\n ref: 'rangeFromMustBeLessThanTo',\n kind: LabelKind.MESSAGE,\n purpose: \"Error shown when a range field's start exceeds its end\",\n },\n // Uniqueness pre-validation messages\n {\n ref: 'uniqueFieldChecking',\n kind: LabelKind.MESSAGE,\n purpose: \"Status shown while a field's value is being checked for uniqueness\",\n },\n {\n ref: 'uniqueFieldConflict',\n kind: LabelKind.MESSAGE,\n purpose: 'Error shown when a unique field value is already taken',\n },\n {\n ref: 'uniqueFieldAvailable',\n kind: LabelKind.MESSAGE,\n purpose: 'Confirmation that a unique field value is available',\n },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_FORM_MESSAGE, LowLevelFormMessageLabels);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/combobox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAyB9B,OAAO,KAAK,EAAE,aAAa,EAAe,qBAAqB,EAAoC,MAAM,6BAA6B,CAAA;AAEtI,QAAA,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/combobox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAyB9B,OAAO,KAAK,EAAE,aAAa,EAAe,qBAAqB,EAAoC,MAAM,6BAA6B,CAAA;AAEtI,QAAA,MAAM,QAAQ,0GAwNZ,CAAA;AAGF,QAAA,MAAM,gBAAgB,kHA8NpB,CAAA;AAWF,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -5,7 +5,7 @@ import { cn, useIconRegistry, StandardIconReference, IconSize, useI18n, useUI, B
|
|
|
5
5
|
import { ButtonVariants_Variant } from "@wildo-ai/saas-frontend-lib";
|
|
6
6
|
import { FormControlVariant, FrontendComponentType, UIBehavior } from "@wildo-ai/presets-components-models";
|
|
7
7
|
import { HorizontalAlign } from "@wildo-ai/zod-decorators";
|
|
8
|
-
const Combobox = React.forwardRef(function ComboboxInner({ schema, name, options, value: controlledValue, onChange, onBlur, defaultValue, placeholder, searchPlaceholder, emptyMessage, disabled, readOnly, className, autoFocus, size = "md", renderOption, renderSelectedValue, onClear, leadingAdornment, onSearchChange, isLoading, shouldFilter = true, onOpenChange: onOpenChangeProp, surfacePolicyOverride, }, ref) {
|
|
8
|
+
const Combobox = React.forwardRef(function ComboboxInner({ schema, name, options, value: controlledValue, onChange, onBlur, defaultValue, placeholder, searchPlaceholder, emptyMessage, disabled, readOnly, className, autoFocus, size = "md", renderOption, renderSelectedValue, onClear, leadingAdornment, onSearchChange, isLoading, shouldFilter = true, onOpenChange: onOpenChangeProp, listFooter, surfacePolicyOverride, }, ref) {
|
|
9
9
|
const [open, setOpen] = React.useState(false);
|
|
10
10
|
const [internalValue, setInternalValue] = React.useState(defaultValue);
|
|
11
11
|
const { renderIcon } = useIconRegistry();
|
|
@@ -83,15 +83,15 @@ const Combobox = React.forwardRef(function ComboboxInner({ schema, name, options
|
|
|
83
83
|
}, children: renderIcon(StandardIconReference.CLOSE, { size: IconSize.SM }) })), renderIcon(StandardIconReference.CHEVRONS_UP_DOWN, {
|
|
84
84
|
size: IconSize.SM,
|
|
85
85
|
className: "ms-2 shrink-0 opacity-[var(--opacity-muted)]",
|
|
86
|
-
})] }) }),
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
})] }) }), _jsxs(PopoverContent, { className: "w-[--radix-popover-trigger-width] p-0", align: HorizontalAlign.START, surfacePolicyOverride: surfacePolicyOverride, children: [_jsxs(Command, { shouldFilter: shouldFilter, children: [_jsx(CommandInput, { placeholder: searchPlaceholder ?? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD, 'searchPlaceholder'), onValueChange: onSearchChange }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: isLoading
|
|
87
|
+
? _jsx(LoadingIndicator, {})
|
|
88
|
+
: (emptyMessage ?? tComponent(FrontendComponentType.LOW_LEVEL_FORM_FIELD, 'noResults')) }), _jsx(CommandGroup, { children: options.map((option) => {
|
|
89
|
+
const isSelected = option.value === currentValue;
|
|
90
|
+
return (_jsxs(CommandItem, { value: option.value, keywords: [option.label], disabled: option.disabled, onSelect: handleSelect, children: [renderIcon(StandardIconReference.CHECK, {
|
|
91
|
+
size: IconSize.SM,
|
|
92
|
+
className: cn("me-2 shrink-0", isSelected ? "opacity-100" : "opacity-0"),
|
|
93
|
+
}), renderOption ? renderOption(option, isSelected) : option.label] }, option.value));
|
|
94
|
+
}) })] })] }), listFooter ? (_jsx("div", { "data-slot": "combobox-list-footer", className: "border-t border-border px-element py-element-sm", children: listFooter })) : null] })] }));
|
|
95
95
|
});
|
|
96
96
|
Combobox.displayName = "Combobox";
|
|
97
97
|
const ComboboxMultiple = React.forwardRef(function ComboboxMultipleInner({ schema, name, options, value: controlledValue, onChange, onBlur, defaultValue, placeholder, searchPlaceholder, emptyMessage, disabled, readOnly, className, autoFocus, size = "md", maxDisplayedBadges = 5, showSelectAll = true, renderOption, renderSelectedValue, onSearchChange, isLoading, shouldFilter = true, onOpenChange: onOpenChangeProp, surfacePolicyOverride, }, ref) {
|