@saastro/forms 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3025,6 +3025,69 @@ declare global {
3025
3025
  */
3026
3026
  declare function recaptchaPlugin(config: RecaptchaPluginConfig): FormPlugin;
3027
3027
 
3028
+ /**
3029
+ * ============================================
3030
+ * TURNSTILE PLUGIN - Cloudflare Turnstile
3031
+ * ============================================
3032
+ *
3033
+ * Mirrors `recaptchaPlugin` but for Cloudflare Turnstile. Unlike
3034
+ * reCAPTCHA v3 (purely programmatic), Turnstile is widget-based: it must
3035
+ * be rendered into a DOM element. This plugin renders the widget in
3036
+ * explicit + `execution: 'execute'` mode (so it only challenges at submit
3037
+ * time) into a container it manages, captures the token via the success
3038
+ * callback, and attaches it to every submission via `transformValues`.
3039
+ *
3040
+ * The token field defaults to `_captchaToken` — the canonical field the
3041
+ * Hub submit helper (`createHubFormSubmit`) extracts and forwards to the
3042
+ * worker as `captchaToken`.
3043
+ */
3044
+ interface TurnstilePluginConfig {
3045
+ /** Cloudflare Turnstile site key. */
3046
+ siteKey: string;
3047
+ /** Field name for the token in submitted values (default: '_captchaToken'). */
3048
+ tokenField?: string;
3049
+ /**
3050
+ * Widget appearance. 'interaction-only' (default) keeps it invisible
3051
+ * unless Cloudflare decides a challenge is needed — closest to the
3052
+ * reCAPTCHA v3 UX. 'always' renders a visible widget.
3053
+ */
3054
+ appearance?: 'always' | 'execute' | 'interaction-only';
3055
+ /**
3056
+ * CSS selector for the element to render the widget into. Defaults to
3057
+ * `[data-saastro-turnstile]` (rendered inline by `HubForm`). If no such
3058
+ * element exists, the plugin creates a fixed, bottom-right container so
3059
+ * an interactive challenge can still surface.
3060
+ */
3061
+ container?: string;
3062
+ }
3063
+ interface TurnstileApi {
3064
+ render: (el: HTMLElement | string, options: Record<string, unknown>) => string;
3065
+ execute: (widgetId?: string, options?: Record<string, unknown>) => void;
3066
+ reset: (widgetId?: string) => void;
3067
+ remove: (widgetId?: string) => void;
3068
+ getResponse: (widgetId?: string) => string | undefined;
3069
+ }
3070
+ declare global {
3071
+ interface Window {
3072
+ turnstile?: TurnstileApi;
3073
+ }
3074
+ }
3075
+ /**
3076
+ * Cloudflare Turnstile plugin.
3077
+ *
3078
+ * @example
3079
+ * ```tsx
3080
+ * import { turnstilePlugin, PluginManager, FormBuilder } from '@saastro/forms';
3081
+ *
3082
+ * const pm = new PluginManager();
3083
+ * pm.register(turnstilePlugin({ siteKey: '0x4AAAAAAA...' }));
3084
+ * ```
3085
+ *
3086
+ * With `HubForm`, this is wired automatically when the form schema
3087
+ * declares `meta.captchaProvider === 'turnstile'`.
3088
+ */
3089
+ declare function turnstilePlugin(config: TurnstilePluginConfig): FormPlugin;
3090
+
3028
3091
  /**
3029
3092
  * ============================================
3030
3093
  * SHADCN/UI PRESET - Component Registry
@@ -3870,4 +3933,4 @@ declare function getFieldClass(formLayout?: {
3870
3933
  */
3871
3934
  declare function getHiddenClasses(hidden?: Partial<Record<Breakpoint, 'visible' | 'hidden'>>): string;
3872
3935
 
3873
- export { type AccordionContentProps, type AccordionItemProps, type AccordionProps, type AccordionTriggerProps, BUILD_METHODS, BUILTIN_RESOLVERS, type BaseFieldProps, type Breakpoint$1 as Breakpoint, type BuiltinTransform, type ButtonCardFieldProps, type ButtonCardOption, type ButtonCheckboxFieldProps, type ButtonConfig, type ButtonProps, type ButtonRadioFieldProps, COMMON_CLASSES, COMMON_METHODS, COMMON_STRINGS, type CalendarProps, type CheckboxFieldProps, type CheckboxGroupFieldProps, type CheckboxProps, type ColumnsValue, type ComboboxFieldProps, type CommandEmptyProps, type CommandFieldProps, type CommandGroupProps, type CommandInputProps, type CommandItemProps, type CommandListProps, type CommandProps, type ComponentName, type ComponentOverrides, ComponentProvider, type ComponentProviderProps, type ComponentRegistry, type ComponentRegistryInput, ComponentResolver, type ComponentResolverConfig, type Condition, type ConditionGroup, type ConditionOperator, type CreateHubFormSubmitOptions, type CurrencyFieldProps, type CustomSubmitAction, type CustomSubmitConfig, DEFAULT_HUB_URL, type DatabowlConfig, type DateFieldProps, type DateRangeFieldProps, type DefaultSubmitConfig, type DefinePlugin, type DialogContentProps, type DialogDescriptionProps, type DialogHeaderProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, type EmailProvider, type EmailSubmitAction, type EndpointConfig, FIELD_DEFAULTS, FieldBuilder, type FieldConfig, type FieldDescriptionProps, type FieldErrorProps, type FieldLabelProps, type FieldLayoutConfig, type FieldMapEntry, type FieldMapping, type FieldMappingConfig, type FieldProps, FieldRenderer, type FieldResolver, type FieldTransformFn, type Fields, type FileFieldProps, Form, FormBuilder, type FormButtonProps, type FormButtons, FormComponentsProvider, type FormComponentsProviderProps, type FormConfig, type FormControlProps, type FormFieldProps, type FormLayout, type FormPlugin, type FormProps, type FormRef, type FormStepsInfo, type GapValue, type GlobModules, type HiddenFieldProps, type HtmlFieldProps, type HttpAuthConfig, type HttpBodyConfig, type HttpEndpointConfig, type HttpRetryConfig, type HttpSubmitAction, HubForm, type HubFormProps, type InputGroupFieldProps, type InputOTPGroupProps, type InputOTPProps, type InputOTPSlotProps, type InputProps, type InputSize, type IntegrationSubmitAction, InternalComponentProvider, type InternalComponentProviderProps, type LabelProps, MissingComponentFallback, type MissingComponentFallbackProps, type NativeSelectFieldProps, type NativeSelectProps, OPTION_BASED_TYPES, type Option, type OtpFieldProps, type PartialComponentRegistry, PluginManager, type PopoverContentProps, type PopoverProps, type PopoverTriggerProps, type PropertyMapping, type RadioFieldProps, type RadioGroupItemProps, type RadioGroupProps, type RangeFieldProps, type RecaptchaConfig, type RecaptchaPluginConfig, type RepeaterFieldProps, type ResolvedComponents, SUSPENSE_CONFIG, type SchemaType, type SelectContentProps, type SelectFieldProps, type SelectItemProps, type SelectProps, type SelectTriggerProps, type SelectValueProps, type SeparatorProps, type SerializableFieldResolver, type SerializationHint, type SliderFieldProps, type SliderProps, type Step, type StepCondition, type StepInfo, type StepStatus, type Steps, StepsAccordion, StepsNavigation, StepsProgress, type SubmitAction, type SubmitActionCondition, type SubmitActionNode, type SubmitActionResult, type SubmitActionType, type SubmitActionsResult, type SubmitConfig, type SubmitConfirmationConfig, type SubmitExecutionConfig, type SubmitTrigger, type SubmitTriggerType, type SubmitType, type SwitchFieldProps, type SwitchGroupFieldProps, type SwitchProps, TYPE_SPECIFIC_PROPERTIES, type TestDataLocale, type TestDataOptions, type TextFieldProps, type TextareaFieldProps, type TextareaProps, type TooltipContentProps, type TooltipProps, type TooltipProviderProps, type TooltipTriggerProps, type UseSubmitConfirmationReturn, VALIDATION_METHODS, type ValidateComponentRegistry, type ValidationContext, type ValidationPresetMeta, type ValidationRules, type WebhookSubmitAction, analyticsPlugin, applyBuiltinTransform, applyFieldMapping, applyFieldMappingSync, applyFieldTransforms, applyTransform, autosavePlugin, compileValidationRules, configureComponents, coreComponents, createComponentRegistry, createHubFormSubmit, createMissingComponentPlaceholder, createShadcnRegistry, databowlAction, databowlPlugin, defaultSubmit, definePlugin, detectLocale, executeCustomAction, executeEmailAction, executeHttpAction, executeSubmitAction, executeSubmitActions, executeSubmitActionsByTrigger, executeWebhookAction, fieldTypeComponents, generateFieldValue, generateTestData, getActionsByTrigger, getAllKnownMethods, getAvailablePresets, getComponentResolver, getFieldClass, getFormGridClass, getHiddenClasses, getInstallCommand, getMinDelayMs, getMissingComponents, getRequiredComponents, globalPluginManager, groupMissingByPackage, iconVariants, iconVariantsConfig, inputVariants, inputVariantsConfig, isAdvancedMapping, isValidationRules, isZodSchema, localStoragePlugin, mergeComponentRegistries, parseGlobModules, pxToRem, recaptchaPlugin, registerPreset, resolvePreset, resolveValue, resolveValueSync, textareaVariants, textareaVariantsConfig, useComponentMode, useComponents, useComputedFields, useFormLayout, useFormState, useFormStepsInfo, useHasComponentProvider, useHiddenFieldResolvers, usePartialComponents, useRecaptcha, useSubmitActionTriggers, useSubmitConfirmation, withComponents };
3936
+ export { type AccordionContentProps, type AccordionItemProps, type AccordionProps, type AccordionTriggerProps, BUILD_METHODS, BUILTIN_RESOLVERS, type BaseFieldProps, type Breakpoint$1 as Breakpoint, type BuiltinTransform, type ButtonCardFieldProps, type ButtonCardOption, type ButtonCheckboxFieldProps, type ButtonConfig, type ButtonProps, type ButtonRadioFieldProps, COMMON_CLASSES, COMMON_METHODS, COMMON_STRINGS, type CalendarProps, type CheckboxFieldProps, type CheckboxGroupFieldProps, type CheckboxProps, type ColumnsValue, type ComboboxFieldProps, type CommandEmptyProps, type CommandFieldProps, type CommandGroupProps, type CommandInputProps, type CommandItemProps, type CommandListProps, type CommandProps, type ComponentName, type ComponentOverrides, ComponentProvider, type ComponentProviderProps, type ComponentRegistry, type ComponentRegistryInput, ComponentResolver, type ComponentResolverConfig, type Condition, type ConditionGroup, type ConditionOperator, type CreateHubFormSubmitOptions, type CurrencyFieldProps, type CustomSubmitAction, type CustomSubmitConfig, DEFAULT_HUB_URL, type DatabowlConfig, type DateFieldProps, type DateRangeFieldProps, type DefaultSubmitConfig, type DefinePlugin, type DialogContentProps, type DialogDescriptionProps, type DialogHeaderProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, type EmailProvider, type EmailSubmitAction, type EndpointConfig, FIELD_DEFAULTS, FieldBuilder, type FieldConfig, type FieldDescriptionProps, type FieldErrorProps, type FieldLabelProps, type FieldLayoutConfig, type FieldMapEntry, type FieldMapping, type FieldMappingConfig, type FieldProps, FieldRenderer, type FieldResolver, type FieldTransformFn, type Fields, type FileFieldProps, Form, FormBuilder, type FormButtonProps, type FormButtons, FormComponentsProvider, type FormComponentsProviderProps, type FormConfig, type FormControlProps, type FormFieldProps, type FormLayout, type FormPlugin, type FormProps, type FormRef, type FormStepsInfo, type GapValue, type GlobModules, type HiddenFieldProps, type HtmlFieldProps, type HttpAuthConfig, type HttpBodyConfig, type HttpEndpointConfig, type HttpRetryConfig, type HttpSubmitAction, HubForm, type HubFormProps, type InputGroupFieldProps, type InputOTPGroupProps, type InputOTPProps, type InputOTPSlotProps, type InputProps, type InputSize, type IntegrationSubmitAction, InternalComponentProvider, type InternalComponentProviderProps, type LabelProps, MissingComponentFallback, type MissingComponentFallbackProps, type NativeSelectFieldProps, type NativeSelectProps, OPTION_BASED_TYPES, type Option, type OtpFieldProps, type PartialComponentRegistry, PluginManager, type PopoverContentProps, type PopoverProps, type PopoverTriggerProps, type PropertyMapping, type RadioFieldProps, type RadioGroupItemProps, type RadioGroupProps, type RangeFieldProps, type RecaptchaConfig, type RecaptchaPluginConfig, type RepeaterFieldProps, type ResolvedComponents, SUSPENSE_CONFIG, type SchemaType, type SelectContentProps, type SelectFieldProps, type SelectItemProps, type SelectProps, type SelectTriggerProps, type SelectValueProps, type SeparatorProps, type SerializableFieldResolver, type SerializationHint, type SliderFieldProps, type SliderProps, type Step, type StepCondition, type StepInfo, type StepStatus, type Steps, StepsAccordion, StepsNavigation, StepsProgress, type SubmitAction, type SubmitActionCondition, type SubmitActionNode, type SubmitActionResult, type SubmitActionType, type SubmitActionsResult, type SubmitConfig, type SubmitConfirmationConfig, type SubmitExecutionConfig, type SubmitTrigger, type SubmitTriggerType, type SubmitType, type SwitchFieldProps, type SwitchGroupFieldProps, type SwitchProps, TYPE_SPECIFIC_PROPERTIES, type TestDataLocale, type TestDataOptions, type TextFieldProps, type TextareaFieldProps, type TextareaProps, type TooltipContentProps, type TooltipProps, type TooltipProviderProps, type TooltipTriggerProps, type TurnstilePluginConfig, type UseSubmitConfirmationReturn, VALIDATION_METHODS, type ValidateComponentRegistry, type ValidationContext, type ValidationPresetMeta, type ValidationRules, type WebhookSubmitAction, analyticsPlugin, applyBuiltinTransform, applyFieldMapping, applyFieldMappingSync, applyFieldTransforms, applyTransform, autosavePlugin, compileValidationRules, configureComponents, coreComponents, createComponentRegistry, createHubFormSubmit, createMissingComponentPlaceholder, createShadcnRegistry, databowlAction, databowlPlugin, defaultSubmit, definePlugin, detectLocale, executeCustomAction, executeEmailAction, executeHttpAction, executeSubmitAction, executeSubmitActions, executeSubmitActionsByTrigger, executeWebhookAction, fieldTypeComponents, generateFieldValue, generateTestData, getActionsByTrigger, getAllKnownMethods, getAvailablePresets, getComponentResolver, getFieldClass, getFormGridClass, getHiddenClasses, getInstallCommand, getMinDelayMs, getMissingComponents, getRequiredComponents, globalPluginManager, groupMissingByPackage, iconVariants, iconVariantsConfig, inputVariants, inputVariantsConfig, isAdvancedMapping, isValidationRules, isZodSchema, localStoragePlugin, mergeComponentRegistries, parseGlobModules, pxToRem, recaptchaPlugin, registerPreset, resolvePreset, resolveValue, resolveValueSync, textareaVariants, textareaVariantsConfig, turnstilePlugin, useComponentMode, useComponents, useComputedFields, useFormLayout, useFormState, useFormStepsInfo, useHasComponentProvider, useHiddenFieldResolvers, usePartialComponents, useRecaptcha, useSubmitActionTriggers, useSubmitConfirmation, withComponents };
package/dist/index.js CHANGED
@@ -6071,6 +6071,156 @@ function recaptchaPlugin(config) {
6071
6071
  });
6072
6072
  }
6073
6073
 
6074
+ // src/plugins/turnstile.ts
6075
+ var SCRIPT_SRC = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
6076
+ var TOKEN_TIMEOUT_MS = 2e4;
6077
+ function waitForTurnstile(timeoutMs = 1e4) {
6078
+ return new Promise((resolve, reject) => {
6079
+ if (typeof window === "undefined") {
6080
+ reject(new Error("turnstile: no window"));
6081
+ return;
6082
+ }
6083
+ if (window.turnstile) {
6084
+ resolve(window.turnstile);
6085
+ return;
6086
+ }
6087
+ const start = Date.now();
6088
+ const tick = () => {
6089
+ if (window.turnstile) {
6090
+ resolve(window.turnstile);
6091
+ } else if (Date.now() - start > timeoutMs) {
6092
+ reject(new Error("turnstile: script did not load"));
6093
+ } else {
6094
+ setTimeout(tick, 100);
6095
+ }
6096
+ };
6097
+ tick();
6098
+ });
6099
+ }
6100
+ function turnstilePlugin(config) {
6101
+ const {
6102
+ siteKey,
6103
+ tokenField = "_captchaToken",
6104
+ appearance = "interaction-only",
6105
+ container
6106
+ } = config;
6107
+ let scriptElement = null;
6108
+ let createdContainer = null;
6109
+ let widgetId;
6110
+ let lastToken = null;
6111
+ let pending = null;
6112
+ const resolveContainer = () => {
6113
+ if (container) {
6114
+ const found = document.querySelector(container);
6115
+ if (found) return found;
6116
+ }
6117
+ const byData = document.querySelector("[data-saastro-turnstile]");
6118
+ if (byData) return byData;
6119
+ if (!createdContainer) {
6120
+ createdContainer = document.createElement("div");
6121
+ createdContainer.setAttribute("data-saastro-turnstile-fallback", "");
6122
+ createdContainer.style.position = "fixed";
6123
+ createdContainer.style.bottom = "12px";
6124
+ createdContainer.style.right = "12px";
6125
+ createdContainer.style.zIndex = "2147483647";
6126
+ document.body.appendChild(createdContainer);
6127
+ }
6128
+ return createdContainer;
6129
+ };
6130
+ const ensureWidget = async () => {
6131
+ const api = await waitForTurnstile();
6132
+ if (widgetId === void 0) {
6133
+ const el = resolveContainer();
6134
+ widgetId = api.render(el, {
6135
+ sitekey: siteKey,
6136
+ appearance,
6137
+ execution: "execute",
6138
+ callback: (token) => {
6139
+ lastToken = token;
6140
+ pending?.resolve(token);
6141
+ pending = null;
6142
+ },
6143
+ "error-callback": () => {
6144
+ pending?.reject(new Error("turnstile: challenge failed"));
6145
+ pending = null;
6146
+ return true;
6147
+ },
6148
+ "expired-callback": () => {
6149
+ lastToken = null;
6150
+ }
6151
+ });
6152
+ }
6153
+ return api;
6154
+ };
6155
+ return definePlugin({
6156
+ name: "turnstile",
6157
+ version: "1.0.0",
6158
+ description: "Cloudflare Turnstile \u2014 widget render and token generation",
6159
+ onFormInit() {
6160
+ if (typeof window === "undefined") return;
6161
+ if (!window.turnstile && !document.querySelector('script[src*="turnstile/v0/api.js"]')) {
6162
+ scriptElement = document.createElement("script");
6163
+ scriptElement.src = SCRIPT_SRC;
6164
+ scriptElement.async = true;
6165
+ scriptElement.defer = true;
6166
+ document.body.appendChild(scriptElement);
6167
+ }
6168
+ void ensureWidget().catch(() => {
6169
+ });
6170
+ },
6171
+ async transformValues(values) {
6172
+ if (typeof window === "undefined") return values;
6173
+ try {
6174
+ const api = await ensureWidget();
6175
+ const token = await new Promise((resolve, reject) => {
6176
+ pending = { resolve, reject };
6177
+ const timer = setTimeout(() => {
6178
+ if (pending) {
6179
+ pending = null;
6180
+ reject(new Error("turnstile: token timeout"));
6181
+ }
6182
+ }, TOKEN_TIMEOUT_MS);
6183
+ const wrappedResolve = (t) => {
6184
+ clearTimeout(timer);
6185
+ resolve(t);
6186
+ };
6187
+ const wrappedReject = (e) => {
6188
+ clearTimeout(timer);
6189
+ reject(e);
6190
+ };
6191
+ pending = { resolve: wrappedResolve, reject: wrappedReject };
6192
+ lastToken = null;
6193
+ api.reset(widgetId);
6194
+ api.execute(widgetId);
6195
+ });
6196
+ return { ...values, [tokenField]: token };
6197
+ } catch (error) {
6198
+ console.error("turnstilePlugin: failed to get token:", error);
6199
+ return values;
6200
+ }
6201
+ },
6202
+ cleanup() {
6203
+ if (typeof window !== "undefined" && window.turnstile && widgetId !== void 0) {
6204
+ try {
6205
+ window.turnstile.remove(widgetId);
6206
+ } catch {
6207
+ }
6208
+ }
6209
+ widgetId = void 0;
6210
+ lastToken = null;
6211
+ pending = null;
6212
+ if (createdContainer?.parentNode) {
6213
+ createdContainer.parentNode.removeChild(createdContainer);
6214
+ createdContainer = null;
6215
+ }
6216
+ if (scriptElement?.parentNode) {
6217
+ scriptElement.parentNode.removeChild(scriptElement);
6218
+ scriptElement = null;
6219
+ }
6220
+ }
6221
+ });
6222
+ }
6223
+
6074
6224
  // src/presets/shadcn.ts
6075
6225
  function createComponentRegistry(components) {
6076
6226
  return {
@@ -6901,6 +7051,13 @@ function createHubFormSubmit(opts) {
6901
7051
  // src/components/HubForm.tsx
6902
7052
  import { useEffect as useEffect8, useMemo as useMemo7, useState as useState5 } from "react";
6903
7053
  import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
7054
+ function readCaptchaMeta(schema) {
7055
+ const meta = schema.meta;
7056
+ return {
7057
+ captchaProvider: meta?.captchaProvider,
7058
+ captchaSiteKey: meta?.captchaSiteKey
7059
+ };
7060
+ }
6904
7061
  function isRenderableSchema(value) {
6905
7062
  if (!value || typeof value !== "object") return false;
6906
7063
  const schema = value;
@@ -6970,6 +7127,18 @@ function HubForm({
6970
7127
  }
6971
7128
  };
6972
7129
  }, [hubUrl, siteId, formSlug, onSuccess, onError]);
7130
+ const captcha = useMemo7(() => {
7131
+ if (state.status !== "ready") return void 0;
7132
+ const { captchaProvider, captchaSiteKey } = readCaptchaMeta(state.schema);
7133
+ if (!captchaProvider || !captchaSiteKey) return void 0;
7134
+ const pm = new PluginManager();
7135
+ if (captchaProvider === "turnstile") {
7136
+ pm.register(turnstilePlugin({ siteKey: captchaSiteKey, tokenField: "_captchaToken" }));
7137
+ } else {
7138
+ pm.register(recaptchaPlugin({ siteKey: captchaSiteKey, tokenField: "_captchaToken" }));
7139
+ }
7140
+ return { pm, provider: captchaProvider };
7141
+ }, [state]);
6973
7142
  if (state.status === "loading") {
6974
7143
  return loadingFallback ?? /* @__PURE__ */ jsx14("div", { "data-saastro-hubform-loading": true, style: loadingStyle, children: "Loading\u2026" });
6975
7144
  }
@@ -6990,9 +7159,13 @@ function HubForm({
6990
7159
  }
6991
7160
  const config = {
6992
7161
  ...state.schema,
6993
- submit: wrappedSubmit
7162
+ submit: wrappedSubmit,
7163
+ ...captcha ? { pluginManager: captcha.pm } : {}
6994
7164
  };
6995
- return /* @__PURE__ */ jsx14(Form, { ...formProps, config });
7165
+ return /* @__PURE__ */ jsxs11(Fragment3, { children: [
7166
+ /* @__PURE__ */ jsx14(Form, { ...formProps, config }),
7167
+ captcha?.provider === "turnstile" ? /* @__PURE__ */ jsx14("div", { "data-saastro-turnstile": true }) : null
7168
+ ] });
6996
7169
  }
6997
7170
  var loadingStyle = {
6998
7171
  padding: "2rem 1rem",
@@ -7332,6 +7505,7 @@ export {
7332
7505
  resolveValueSync,
7333
7506
  textareaVariants,
7334
7507
  textareaVariantsConfig,
7508
+ turnstilePlugin,
7335
7509
  useComponentMode,
7336
7510
  useComponents,
7337
7511
  useComputedFields,