@uipath/apollo-wind 2.50.0 → 2.52.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.
Files changed (59) hide show
  1. package/dist/components/forms/field-renderer.cjs +80 -6
  2. package/dist/components/forms/field-renderer.js +80 -6
  3. package/dist/components/forms/form-designer.cjs +10 -10
  4. package/dist/components/forms/form-designer.js +10 -10
  5. package/dist/components/forms/form-schema.d.ts +38 -2
  6. package/dist/components/forms/index.cjs +15 -5
  7. package/dist/components/forms/index.d.ts +7 -6
  8. package/dist/components/forms/index.js +6 -5
  9. package/dist/components/forms/metadata-form.cjs +97 -37
  10. package/dist/components/forms/metadata-form.d.ts +11 -3
  11. package/dist/components/forms/metadata-form.js +94 -37
  12. package/dist/components/forms/rules-engine.cjs +14 -3
  13. package/dist/components/forms/rules-engine.d.ts +16 -0
  14. package/dist/components/forms/rules-engine.js +14 -3
  15. package/dist/components/forms/schema-serializer.cjs +10 -0
  16. package/dist/components/forms/schema-serializer.js +10 -0
  17. package/dist/components/forms/string-list-field.cjs +154 -0
  18. package/dist/components/forms/string-list-field.d.ts +29 -0
  19. package/dist/components/forms/string-list-field.js +117 -0
  20. package/dist/components/forms/validation-converter.cjs +68 -23
  21. package/dist/components/forms/validation-converter.d.ts +23 -2
  22. package/dist/components/forms/validation-converter.js +64 -22
  23. package/dist/components/ui/datetime-picker.cjs +3 -1
  24. package/dist/components/ui/datetime-picker.d.ts +4 -0
  25. package/dist/components/ui/datetime-picker.js +3 -1
  26. package/dist/components/ui/form-field.cjs +17 -2
  27. package/dist/components/ui/form-field.d.ts +7 -0
  28. package/dist/components/ui/form-field.js +17 -2
  29. package/dist/components/ui/index.cjs +124 -114
  30. package/dist/components/ui/index.d.ts +3 -2
  31. package/dist/components/ui/index.js +2 -1
  32. package/dist/components/ui/info-tooltip.cjs +61 -0
  33. package/dist/components/ui/info-tooltip.d.ts +10 -0
  34. package/dist/components/ui/info-tooltip.js +27 -0
  35. package/dist/components/ui/prompt-editor/components/EditorToolbar.cjs +18 -2
  36. package/dist/components/ui/prompt-editor/components/EditorToolbar.d.ts +3 -1
  37. package/dist/components/ui/prompt-editor/components/EditorToolbar.js +19 -3
  38. package/dist/components/ui/prompt-editor/components/MarkdownPreview.cjs +4 -2
  39. package/dist/components/ui/prompt-editor/components/MarkdownPreview.js +4 -2
  40. package/dist/components/ui/prompt-editor/plugins/ToolbarActionsPlugin.cjs +14 -4
  41. package/dist/components/ui/prompt-editor/plugins/ToolbarActionsPlugin.js +14 -4
  42. package/dist/components/ui/prompt-editor/prompt-editor-config.cjs +2 -0
  43. package/dist/components/ui/prompt-editor/prompt-editor-config.d.ts +2 -0
  44. package/dist/components/ui/prompt-editor/prompt-editor-config.js +2 -0
  45. package/dist/components/ui/prompt-editor/prompt-editor.cjs +10 -1
  46. package/dist/components/ui/prompt-editor/prompt-editor.js +10 -1
  47. package/dist/components/ui/prompt-editor/types.d.ts +7 -1
  48. package/dist/components/ui/prompt-editor/utils/rich-serialization.cjs +48 -1
  49. package/dist/components/ui/prompt-editor/utils/rich-serialization.d.ts +0 -14
  50. package/dist/components/ui/prompt-editor/utils/rich-serialization.js +50 -3
  51. package/dist/components/ui/select.cjs +1 -1
  52. package/dist/components/ui/select.js +1 -1
  53. package/dist/components/ui/textarea.cjs +1 -1
  54. package/dist/components/ui/textarea.js +1 -1
  55. package/dist/index.cjs +14 -0
  56. package/dist/index.d.ts +7 -2
  57. package/dist/index.js +4 -2
  58. package/dist/styles.css +13 -0
  59. package/package.json +2 -2
@@ -6,13 +6,14 @@ import { z } from "zod/v4";
6
6
  import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../ui/accordion.js";
7
7
  import { Button } from "../ui/button.js";
8
8
  import { ScrollableTabsList, Tabs, TabsContent, TabsTrigger } from "../ui/tabs.js";
9
+ import { TooltipProvider } from "../ui/tooltip.js";
9
10
  import { deepEqual, get } from "../../lib/index.js";
10
11
  import { DataFetcher } from "./data-fetcher.js";
11
12
  import { FormFieldRenderer } from "./field-renderer.js";
12
13
  import { RulesEngine } from "./rules-engine.js";
13
- import { validationConfigToZod } from "./validation-converter.js";
14
+ import { isEmptyFieldValue, validationConfigToZod } from "./validation-converter.js";
14
15
  const DEFAULT_PLUGINS = [];
15
- function MetadataForm({ schema, plugins = DEFAULT_PLUGINS, onSubmit, className, disabled = false, autoComplete, stepVariant = 'wizard', sectionVariant = 'card', activeStepId, onActiveStepChange }) {
16
+ function MetadataForm({ schema, plugins = DEFAULT_PLUGINS, onSubmit, className, disabled = false, autoComplete, stepVariant = 'wizard', sectionVariant = 'card', activeStepId, onActiveStepChange, container = 'form' }) {
16
17
  const [currentStep, setCurrentStep] = useState(0);
17
18
  const [customComponents, setCustomComponents] = useState({});
18
19
  const [isInitialized, setIsInitialized] = useState(false);
@@ -24,6 +25,15 @@ function MetadataForm({ schema, plugins = DEFAULT_PLUGINS, onSubmit, className,
24
25
  }, [
25
26
  schema
26
27
  ]);
28
+ const hasFieldTooltip = useMemo(()=>{
29
+ const sections = [
30
+ ...stableSchema.sections ?? [],
31
+ ...(stableSchema.steps ?? []).flatMap((step)=>step.sections)
32
+ ];
33
+ return sections.some((section)=>section.fields.some((field)=>void 0 !== field.tooltip));
34
+ }, [
35
+ stableSchema
36
+ ]);
27
37
  const zodSchema = useMemo(()=>buildZodSchema(stableSchema), [
28
38
  stableSchema
29
39
  ]);
@@ -73,12 +83,12 @@ function MetadataForm({ schema, plugins = DEFAULT_PLUGINS, onSubmit, className,
73
83
  ]);
74
84
  const contextRef = useRef(context);
75
85
  contextRef.current = context;
76
- const isInitializedRef = useRef(isInitialized);
77
- isInitializedRef.current = isInitialized;
86
+ const initializingRef = useRef(false);
78
87
  useEffect(()=>{
79
88
  const subscription = watch((value, { name })=>{
80
89
  valuesRef.current = value;
81
- if (!name || !isInitializedRef.current) return;
90
+ if (!name) return;
91
+ if (initializingRef.current) return;
82
92
  pluginsRef.current.forEach((plugin)=>{
83
93
  plugin.onValueChange?.(name, get(value, name), contextRef.current);
84
94
  });
@@ -92,9 +102,17 @@ function MetadataForm({ schema, plugins = DEFAULT_PLUGINS, onSubmit, className,
92
102
  const initializeForm = async ()=>{
93
103
  if (stableSchema.initialData) {
94
104
  const data = await loadInitialData(stableSchema.initialData, contextRef.current);
95
- reset(data);
105
+ initializingRef.current = true;
106
+ try {
107
+ reset(data);
108
+ } finally{
109
+ initializingRef.current = false;
110
+ }
111
+ }
112
+ for (const plugin of plugins){
113
+ const result = plugin.onFormInit?.(contextRef.current);
114
+ if (result instanceof Promise) await result;
96
115
  }
97
- for (const plugin of plugins)await plugin.onFormInit?.(contextRef.current);
98
116
  setIsInitialized(true);
99
117
  };
100
118
  initializeForm();
@@ -111,51 +129,89 @@ function MetadataForm({ schema, plugins = DEFAULT_PLUGINS, onSubmit, className,
111
129
  const handleReset = useCallback(()=>reset(), [
112
130
  reset
113
131
  ]);
132
+ const allCustomComponents = useMemo(()=>{
133
+ const fromPlugins = {};
134
+ for (const plugin of plugins)Object.assign(fromPlugins, plugin.components);
135
+ return {
136
+ ...fromPlugins,
137
+ ...customComponents
138
+ };
139
+ }, [
140
+ plugins,
141
+ customComponents
142
+ ]);
143
+ const enterSwallowRef = useRef(null);
144
+ useEffect(()=>{
145
+ const node = enterSwallowRef.current;
146
+ if (!node) return;
147
+ const swallowEnter = (event)=>{
148
+ if ('Enter' !== event.key || event.defaultPrevented) return;
149
+ const target = event.target;
150
+ if (target instanceof HTMLInputElement && 'button' !== target.type) event.preventDefault();
151
+ };
152
+ node.addEventListener('keydown', swallowEnter);
153
+ return ()=>node.removeEventListener('keydown', swallowEnter);
154
+ }, [
155
+ container
156
+ ]);
114
157
  const renderContent = ()=>{
115
158
  if (stableSchema.steps) {
116
159
  if ('tabs' === stepVariant) return /*#__PURE__*/ jsx(TabbedStepForm, {
117
160
  schema: stableSchema,
118
161
  context: context,
119
- customComponents: customComponents,
162
+ customComponents: allCustomComponents,
120
163
  disabled: disabled,
121
164
  sectionVariant: sectionVariant,
122
165
  activeStepId: activeStepId,
123
166
  onActiveStepChange: onActiveStepChange,
124
- onReset: handleReset
167
+ onReset: handleReset,
168
+ onSubmit: 'div' === container ? handleFormSubmit : void 0
125
169
  });
126
170
  return /*#__PURE__*/ jsx(metadata_form_MultiStepForm, {
127
171
  schema: stableSchema,
128
172
  context: context,
129
173
  currentStep: currentStep,
130
174
  setCurrentStep: setCurrentStep,
131
- customComponents: customComponents,
175
+ customComponents: allCustomComponents,
132
176
  disabled: disabled,
133
- sectionVariant: sectionVariant
177
+ sectionVariant: sectionVariant,
178
+ onSubmit: 'div' === container ? handleFormSubmit : void 0
134
179
  });
135
180
  }
136
181
  return /*#__PURE__*/ jsx(metadata_form_SinglePageForm, {
137
182
  schema: stableSchema,
138
183
  context: context,
139
- customComponents: customComponents,
184
+ customComponents: allCustomComponents,
140
185
  disabled: disabled,
141
186
  sectionVariant: sectionVariant
142
187
  });
143
188
  };
189
+ const content = /*#__PURE__*/ jsxs(Fragment, {
190
+ children: [
191
+ renderContent(),
192
+ !stableSchema.steps && /*#__PURE__*/ jsx(metadata_form_FormActions, {
193
+ schema: stableSchema,
194
+ context: context,
195
+ onReset: handleReset,
196
+ onSubmit: 'div' === container ? handleFormSubmit : void 0
197
+ })
198
+ ]
199
+ });
200
+ const body = 'div' === container ? /*#__PURE__*/ jsx("div", {
201
+ className: className,
202
+ ref: enterSwallowRef,
203
+ children: content
204
+ }) : /*#__PURE__*/ jsx("form", {
205
+ onSubmit: handleFormSubmit,
206
+ className: className,
207
+ autoComplete: autoComplete,
208
+ children: content
209
+ });
144
210
  return /*#__PURE__*/ jsx(FormProvider, {
145
211
  ...form,
146
- children: /*#__PURE__*/ jsxs("form", {
147
- onSubmit: handleFormSubmit,
148
- className: className,
149
- autoComplete: autoComplete,
150
- children: [
151
- renderContent(),
152
- !stableSchema.steps && /*#__PURE__*/ jsx(metadata_form_FormActions, {
153
- schema: stableSchema,
154
- context: context,
155
- onReset: handleReset
156
- })
157
- ]
158
- })
212
+ children: hasFieldTooltip ? /*#__PURE__*/ jsx(TooltipProvider, {
213
+ children: body
214
+ }) : body
159
215
  });
160
216
  }
161
217
  function conditionDependencies(conditionGroups) {
@@ -187,7 +243,7 @@ const metadata_form_SinglePageForm = /*#__PURE__*/ react.memo(function({ schema,
187
243
  }, section.id))
188
244
  });
189
245
  });
190
- const metadata_form_MultiStepForm = /*#__PURE__*/ react.memo(function({ schema, context, currentStep, setCurrentStep, customComponents, disabled, sectionVariant }) {
246
+ const metadata_form_MultiStepForm = /*#__PURE__*/ react.memo(function({ schema, context, currentStep, setCurrentStep, customComponents, disabled, sectionVariant, onSubmit }) {
191
247
  const steps = schema.steps || [];
192
248
  const conditionFields = useMemo(()=>conditionDependencies(schema.steps?.map((step)=>step.conditions) ?? []), [
193
249
  schema
@@ -265,7 +321,8 @@ const metadata_form_MultiStepForm = /*#__PURE__*/ react.memo(function({ schema,
265
321
  variant: "default",
266
322
  children: "Next"
267
323
  }) : /*#__PURE__*/ jsx(Button, {
268
- type: "submit",
324
+ type: onSubmit ? 'button' : 'submit',
325
+ onClick: onSubmit,
269
326
  variant: "default",
270
327
  children: "Submit"
271
328
  })
@@ -274,7 +331,7 @@ const metadata_form_MultiStepForm = /*#__PURE__*/ react.memo(function({ schema,
274
331
  ]
275
332
  });
276
333
  });
277
- function TabbedStepForm({ schema, context, customComponents, disabled, sectionVariant, onReset, activeStepId, onActiveStepChange }) {
334
+ function TabbedStepForm({ schema, context, customComponents, disabled, sectionVariant, onReset, activeStepId, onActiveStepChange, onSubmit }) {
278
335
  const steps = schema.steps || [];
279
336
  const conditionFields = useMemo(()=>conditionDependencies(schema.steps?.flatMap((step)=>[
280
337
  step.conditions,
@@ -340,7 +397,7 @@ function TabbedStepForm({ schema, context, customComponents, disabled, sectionVa
340
397
  role: "img",
341
398
  "aria-label": `${errorCount} ${1 === errorCount ? 'issue' : 'issues'}`,
342
399
  title: `${errorCount} ${1 === errorCount ? 'issue' : 'issues'}`,
343
- className: "grid h-4 min-w-4 place-items-center rounded-full bg-error px-1 text-[10px] font-semibold leading-none text-foreground-on-accent",
400
+ className: "grid h-4 min-w-4 place-items-center rounded-full bg-error px-1 text-[10px] font-semibold leading-none text-error-background",
344
401
  children: errorCount
345
402
  })
346
403
  ]
@@ -373,7 +430,8 @@ function TabbedStepForm({ schema, context, customComponents, disabled, sectionVa
373
430
  /*#__PURE__*/ jsx(metadata_form_FormActions, {
374
431
  schema: schema,
375
432
  context: context,
376
- onReset: onReset
433
+ onReset: onReset,
434
+ onSubmit: onSubmit
377
435
  })
378
436
  ]
379
437
  });
@@ -455,7 +513,7 @@ const metadata_form_FormSection = /*#__PURE__*/ react.memo(function({ section, c
455
513
  ]
456
514
  });
457
515
  });
458
- const metadata_form_FormActions = /*#__PURE__*/ react.memo(function({ schema, context, onReset }) {
516
+ const metadata_form_FormActions = /*#__PURE__*/ react.memo(function({ schema, context, onReset, onSubmit }) {
459
517
  const { isSubmitting } = useFormState({
460
518
  control: context.form.control
461
519
  });
@@ -484,7 +542,8 @@ const metadata_form_FormActions = /*#__PURE__*/ react.memo(function({ schema, co
484
542
  children: action.label
485
543
  }, action.id);
486
544
  return /*#__PURE__*/ jsx(Button, {
487
- type: 'submit' === action.type ? 'submit' : 'button',
545
+ type: 'submit' !== action.type || onSubmit ? 'button' : 'submit',
546
+ onClick: 'submit' === action.type && onSubmit ? onSubmit : void 0,
488
547
  variant: action.variant || 'default',
489
548
  disabled: action.disabled || 'submit' === action.type && isSubmitting,
490
549
  children: action.loading && isSubmitting ? 'Loading...' : action.label
@@ -515,7 +574,7 @@ function buildZodSchema(schema) {
515
574
  } : shouldIncludeRequiredInBase ? {
516
575
  required: true
517
576
  } : void 0;
518
- shape[field.name] = validationConfigToZod(validationConfig, field.type);
577
+ shape[field.name] = validationConfigToZod(validationConfig, field.type, 'custom' === field.type ? field.valueType : void 0);
519
578
  });
520
579
  const baseSchema = z.object(shape);
521
580
  if (0 === dynamicValidationFields.length) return baseSchema;
@@ -527,9 +586,7 @@ function buildZodSchema(schema) {
527
586
  const ruleResult = RulesEngine.applyRules(rules, values, {});
528
587
  const isRequired = true === ruleResult.required || staticRequired;
529
588
  if (isRequired) {
530
- const value = values[name];
531
- const isEmpty = null == value || '' === value || Array.isArray(value) && 0 === value.length;
532
- if (isEmpty) ctx.addIssue({
589
+ if (isEmptyFieldValue(values[name])) ctx.addIssue({
533
590
  code: z.ZodIssueCode.custom,
534
591
  message: customRequiredMessage || 'This field is required',
535
592
  path: [
@@ -544,4 +601,4 @@ async function loadInitialData(initialData, _context) {
544
601
  if (!initialData) return {};
545
602
  return initialData;
546
603
  }
547
- export { MetadataForm };
604
+ export { MetadataForm, useWatch };
@@ -76,12 +76,23 @@ class RulesEngine {
76
76
  return state;
77
77
  }
78
78
  static evaluateExpression(expression, values) {
79
+ const result = RulesEngine.tryEvaluateExpression(expression, values);
80
+ if (result.ok) return result.value;
81
+ console.error('Expression evaluation error:', result.error);
82
+ return false;
83
+ }
84
+ static tryEvaluateExpression(expression, values) {
79
85
  try {
80
86
  const ast = external_jsep_default()(expression);
81
- return RulesEngine.evaluateNode(ast, values);
87
+ return {
88
+ ok: true,
89
+ value: RulesEngine.evaluateNode(ast, values)
90
+ };
82
91
  } catch (error) {
83
- console.error('Expression evaluation error:', error);
84
- return false;
92
+ return {
93
+ ok: false,
94
+ error
95
+ };
85
96
  }
86
97
  }
87
98
  static evaluateNode(node, values) {
@@ -33,6 +33,22 @@ export declare class RulesEngine {
33
33
  * - "total >= 100 ? 'discount' : 'regular'"
34
34
  */
35
35
  static evaluateExpression(expression: string, values: Record<string, unknown>): unknown;
36
+ /**
37
+ * Like `evaluateExpression`, but reports *why* there is no value.
38
+ *
39
+ * `evaluateExpression` returns `false` both for an expression that legitimately evaluates
40
+ * to false and for one the evaluator cannot handle at all — `value.some(x)` parses fine and
41
+ * then throws on the unsupported `CallExpression`. Callers that treat falsey as "failed the
42
+ * check" would turn an unsupported expression into a permanently failing one, so they need
43
+ * to tell the two apart.
44
+ */
45
+ static tryEvaluateExpression(expression: string, values: Record<string, unknown>): {
46
+ ok: true;
47
+ value: unknown;
48
+ } | {
49
+ ok: false;
50
+ error: unknown;
51
+ };
36
52
  /**
37
53
  * Minimal AST evaluator - only supports operators needed for form rules
38
54
  */
@@ -36,12 +36,23 @@ class RulesEngine {
36
36
  return state;
37
37
  }
38
38
  static evaluateExpression(expression, values) {
39
+ const result = RulesEngine.tryEvaluateExpression(expression, values);
40
+ if (result.ok) return result.value;
41
+ console.error('Expression evaluation error:', result.error);
42
+ return false;
43
+ }
44
+ static tryEvaluateExpression(expression, values) {
39
45
  try {
40
46
  const ast = jsep(expression);
41
- return RulesEngine.evaluateNode(ast, values);
47
+ return {
48
+ ok: true,
49
+ value: RulesEngine.evaluateNode(ast, values)
50
+ };
42
51
  } catch (error) {
43
- console.error('Expression evaluation error:', error);
44
- return false;
52
+ return {
53
+ ok: false,
54
+ error
55
+ };
45
56
  }
46
57
  }
47
58
  static evaluateNode(node, values) {
@@ -180,6 +180,8 @@ function serializeField(field) {
180
180
  if (field.grid) result.grid = field.grid;
181
181
  if (field.ariaLabel) result.ariaLabel = field.ariaLabel;
182
182
  if (field.ariaDescribedBy) result.ariaDescribedBy = field.ariaDescribedBy;
183
+ if (field.tooltip) result.tooltip = field.tooltip;
184
+ if (field.tooltipAriaLabel) result.tooltipAriaLabel = field.tooltipAriaLabel;
183
185
  if ('options' in field && field.options) result.options = serializeOptions(field.options);
184
186
  if ('rows' in field && field.rows) result.rows = field.rows;
185
187
  if ('min' in field && void 0 !== field.min) result.min = field.min;
@@ -191,7 +193,15 @@ function serializeField(field) {
191
193
  if ('maxSize' in field && field.maxSize) result.maxSize = field.maxSize;
192
194
  if ('showPreview' in field && field.showPreview) result.showPreview = field.showPreview;
193
195
  if ('use12Hour' in field && field.use12Hour) result.use12Hour = field.use12Hour;
196
+ if ('minRows' in field && void 0 !== field.minRows) result.minRows = field.minRows;
197
+ if ('maxLength' in field && void 0 !== field.maxLength) result.maxLength = field.maxLength;
198
+ if ('maxItems' in field && void 0 !== field.maxItems) result.maxItems = field.maxItems;
199
+ if ('emptyMessage' in field && field.emptyMessage) result.emptyMessage = field.emptyMessage;
200
+ if ('searchPlaceholder' in field && field.searchPlaceholder) result.searchPlaceholder = field.searchPlaceholder;
201
+ if ('addItemLabel' in field && field.addItemLabel) result.addItemLabel = field.addItemLabel;
202
+ if ('removeItemAriaLabel' in field && field.removeItemAriaLabel) result.removeItemAriaLabel = field.removeItemAriaLabel;
194
203
  if ('component' in field && field.component) result.component = field.component;
204
+ if ('valueType' in field && field.valueType) result.valueType = field.valueType;
195
205
  if ('componentProps' in field && field.componentProps) result.componentProps = field.componentProps;
196
206
  return result;
197
207
  }
@@ -151,6 +151,8 @@ function serializeField(field) {
151
151
  if (field.grid) result.grid = field.grid;
152
152
  if (field.ariaLabel) result.ariaLabel = field.ariaLabel;
153
153
  if (field.ariaDescribedBy) result.ariaDescribedBy = field.ariaDescribedBy;
154
+ if (field.tooltip) result.tooltip = field.tooltip;
155
+ if (field.tooltipAriaLabel) result.tooltipAriaLabel = field.tooltipAriaLabel;
154
156
  if ('options' in field && field.options) result.options = serializeOptions(field.options);
155
157
  if ('rows' in field && field.rows) result.rows = field.rows;
156
158
  if ('min' in field && void 0 !== field.min) result.min = field.min;
@@ -162,7 +164,15 @@ function serializeField(field) {
162
164
  if ('maxSize' in field && field.maxSize) result.maxSize = field.maxSize;
163
165
  if ('showPreview' in field && field.showPreview) result.showPreview = field.showPreview;
164
166
  if ('use12Hour' in field && field.use12Hour) result.use12Hour = field.use12Hour;
167
+ if ('minRows' in field && void 0 !== field.minRows) result.minRows = field.minRows;
168
+ if ('maxLength' in field && void 0 !== field.maxLength) result.maxLength = field.maxLength;
169
+ if ('maxItems' in field && void 0 !== field.maxItems) result.maxItems = field.maxItems;
170
+ if ('emptyMessage' in field && field.emptyMessage) result.emptyMessage = field.emptyMessage;
171
+ if ('searchPlaceholder' in field && field.searchPlaceholder) result.searchPlaceholder = field.searchPlaceholder;
172
+ if ('addItemLabel' in field && field.addItemLabel) result.addItemLabel = field.addItemLabel;
173
+ if ('removeItemAriaLabel' in field && field.removeItemAriaLabel) result.removeItemAriaLabel = field.removeItemAriaLabel;
165
174
  if ('component' in field && field.component) result.component = field.component;
175
+ if ('valueType' in field && field.valueType) result.valueType = field.valueType;
166
176
  if ('componentProps' in field && field.componentProps) result.componentProps = field.componentProps;
167
177
  return result;
168
178
  }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ formatTemplate: ()=>formatTemplate,
28
+ StringListField: ()=>StringListField
29
+ });
30
+ const jsx_runtime_namespaceObject = require("react/jsx-runtime");
31
+ const external_lucide_react_namespaceObject = require("lucide-react");
32
+ const external_react_namespaceObject = require("react");
33
+ const button_cjs_namespaceObject = require("../ui/button.cjs");
34
+ const form_field_cjs_namespaceObject = require("../ui/form-field.cjs");
35
+ const textarea_cjs_namespaceObject = require("../ui/textarea.cjs");
36
+ function formatTemplate(template, values) {
37
+ return template.replace(/\{\{(\w+)\}\}/g, (match, token)=>token in values ? String(values[token]) : match);
38
+ }
39
+ function StringListField({ field, value, onChange, onBlur, error, disabled = false, required = false, inputRef }) {
40
+ const items = value ?? [];
41
+ const maxItems = field.maxItems ?? 1 / 0;
42
+ const canAdd = !disabled && items.length < maxItems;
43
+ const addItemLabel = field.addItemLabel ?? 'Add';
44
+ const removeItemAriaLabel = field.removeItemAriaLabel ?? 'Remove {{label}} {{position}}';
45
+ const [rowIds, setRowIds] = (0, external_react_namespaceObject.useState)(()=>items.map(()=>crypto.randomUUID()));
46
+ const [prevLength, setPrevLength] = (0, external_react_namespaceObject.useState)(items.length);
47
+ if (prevLength !== items.length) {
48
+ setPrevLength(items.length);
49
+ setRowIds((prev)=>prev.length < items.length ? [
50
+ ...prev,
51
+ ...Array.from({
52
+ length: items.length - prev.length
53
+ }, ()=>crypto.randomUUID())
54
+ ] : prev.slice(0, items.length));
55
+ }
56
+ const addItem = (0, external_react_namespaceObject.useCallback)(()=>{
57
+ setRowIds((prev)=>[
58
+ ...prev,
59
+ crypto.randomUUID()
60
+ ]);
61
+ onChange([
62
+ ...items,
63
+ ''
64
+ ]);
65
+ }, [
66
+ items,
67
+ onChange
68
+ ]);
69
+ const removeItem = (0, external_react_namespaceObject.useCallback)((index)=>{
70
+ setRowIds((prev)=>prev.filter((_, i)=>i !== index));
71
+ onChange(items.filter((_, i)=>i !== index));
72
+ }, [
73
+ items,
74
+ onChange
75
+ ]);
76
+ const updateItem = (0, external_react_namespaceObject.useCallback)((index, next)=>{
77
+ onChange(items.map((item, i)=>i === index ? next : item));
78
+ }, [
79
+ items,
80
+ onChange
81
+ ]);
82
+ return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(form_field_cjs_namespaceObject.FormField, {
83
+ "data-slot": "string-list-field",
84
+ children: [
85
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(form_field_cjs_namespaceObject.FormFieldLabel, {
86
+ required: required,
87
+ tooltip: field.tooltip,
88
+ tooltipAriaLabel: field.tooltipAriaLabel,
89
+ children: field.label
90
+ }),
91
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
92
+ className: "grid gap-1.5",
93
+ children: items.map((item, index)=>/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
94
+ className: "flex items-start gap-2",
95
+ children: [
96
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(textarea_cjs_namespaceObject.Textarea, {
97
+ ref: 0 === index ? inputRef : void 0,
98
+ value: item,
99
+ onChange: (e)=>updateItem(index, e.target.value),
100
+ onBlur: onBlur,
101
+ minRows: field.minRows ?? 2,
102
+ maxLength: field.maxLength,
103
+ disabled: disabled,
104
+ "aria-label": `${field.label} ${index + 1}`,
105
+ "aria-invalid": error ? true : void 0,
106
+ className: "flex-1"
107
+ }),
108
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(button_cjs_namespaceObject.Button, {
109
+ type: "button",
110
+ variant: "ghost",
111
+ size: "sm",
112
+ icon: true,
113
+ disabled: disabled,
114
+ onClick: ()=>removeItem(index),
115
+ "aria-label": formatTemplate(removeItemAriaLabel, {
116
+ label: field.label,
117
+ position: index + 1
118
+ }),
119
+ className: "shrink-0 text-muted-foreground",
120
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_lucide_react_namespaceObject.Trash2, {})
121
+ })
122
+ ]
123
+ }, rowIds[index] ?? index))
124
+ }),
125
+ canAdd && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
126
+ children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(button_cjs_namespaceObject.Button, {
127
+ type: "button",
128
+ variant: "text",
129
+ size: "2xs",
130
+ onClick: addItem,
131
+ children: [
132
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_lucide_react_namespaceObject.Plus, {}),
133
+ addItemLabel
134
+ ]
135
+ })
136
+ }),
137
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(form_field_cjs_namespaceObject.FormFieldDescription, {
138
+ children: field.description
139
+ }),
140
+ /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(form_field_cjs_namespaceObject.FormFieldError, {
141
+ children: error
142
+ })
143
+ ]
144
+ });
145
+ }
146
+ exports.StringListField = __webpack_exports__.StringListField;
147
+ exports.formatTemplate = __webpack_exports__.formatTemplate;
148
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
149
+ "StringListField",
150
+ "formatTemplate"
151
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
152
+ Object.defineProperty(exports, '__esModule', {
153
+ value: true
154
+ });
@@ -0,0 +1,29 @@
1
+ import type * as React from 'react';
2
+ import type { StringListFieldMetadata } from './form-schema';
3
+ /** Interpolate `{{token}}` placeholders; unknown tokens are left untouched. */
4
+ export declare function formatTemplate(template: string, values: Record<string, string | number>): string;
5
+ export interface StringListFieldProps {
6
+ field: StringListFieldMetadata;
7
+ value: string[] | undefined;
8
+ onChange: (value: string[]) => void;
9
+ /** Forwarded to every row so blur-mode validation and touched state work. */
10
+ onBlur?: () => void;
11
+ error?: string;
12
+ disabled?: boolean;
13
+ required?: boolean;
14
+ /**
15
+ * The Controller ref, attached to the first row. react-hook-form's `shouldFocusError`
16
+ * focuses the ref of the first invalid field on a failed submit; without this the list is
17
+ * the one built-in control it cannot reach, so the user is left with an error and no
18
+ * indication of where it is.
19
+ */
20
+ inputRef?: React.Ref<HTMLTextAreaElement>;
21
+ }
22
+ /**
23
+ * Repeated multiline rows with Add / Remove — the `string-list` field type.
24
+ *
25
+ * Rendering it standalone with `field.tooltip` set requires an ancestor `TooltipProvider`:
26
+ * the info trigger is a Radix tooltip, which throws without one. Inside `MetadataForm` this
27
+ * is handled for you — it mounts a provider for schemas that use tooltip metadata.
28
+ */
29
+ export declare function StringListField({ field, value, onChange, onBlur, error, disabled, required, inputRef, }: StringListFieldProps): import("react/jsx-runtime").JSX.Element;