Skip to content

Conversation

@lissavxo
Copy link
Collaborator

@lissavxo lissavxo commented Jan 14, 2026

Related to #66

Description

Added fields param
Create paymentId with provided fields

Test plan

Make sure everythin works fine. Go to the test page and test the example with fields.

Summary by CodeRabbit

  • New Features

    • Added support for custom form fields in PayButton widget, allowing collection of additional user input alongside payment information
    • Added field submission callback to process collected custom field data
  • Documentation

    • Expanded documentation across multiple languages with detailed field parameter specifications, property descriptions, and practical implementation examples

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

Warning

Rate limit exceeded

@lissavxo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between fe2d4dc and 9cab186.

📒 Files selected for processing (4)
  • docs/README.md
  • docs/zh-cn/README.md
  • docs/zh-tw/README.md
  • react/lib/components/Widget/Widget.tsx
📝 Walkthrough

Walkthrough

The PR introduces custom form fields support for PayButton components. It adds a new Field type definition, threads the fields prop through the React component hierarchy (PayButton → PaymentDialog → WidgetContainer → Widget), implements field rendering and validation in the Widget component, extends the createPayment API call to include fields, and documents the feature across English and Chinese README files.

Changes

Cohort / File(s) Summary
Documentation
docs/README.md, docs/zh-cn/README.md, docs/zh-tw/README.md
Added comprehensive documentation sections for the fields parameter (type, structure, examples) and on-fields-submit callback across English and Simplified/Traditional Chinese versions.
Type Definitions
react/lib/util/types.ts
Introduced new Field type export with properties: name, text, type (required) and value, required (optional).
Component Prop Threading
react/lib/components/PayButton/PayButton.tsx, react/lib/components/PaymentDialog/PaymentDialog.tsx, react/lib/components/Widget/WidgetContainer.tsx
Added fields?: Field[] prop to component interfaces and forwarded it through the component tree to enable field data propagation.
Widget Implementation
react/lib/components/Widget/Widget.tsx
Implemented custom field rendering, validation for required fields, field value collection, and onFieldsSubmit callback invocation. Integrated field submission with payment creation flow.
API Integration
react/lib/util/api-client.ts
Extended createPayment function signature to accept optional fields?: Field[] parameter and include fields in the API POST payload.
Core Configuration
paybutton/src/index.tsx
Added fields to the allowedProps array to permit the property via DOM attributes.
Demo
paybutton/dev/demo/index.html
Added a PayButton widget example demonstrating custom field usage with a text input for "name".

Sequence Diagram

sequenceDiagram
    participant User
    participant Widget
    participant API as createPayment<br/>(API Client)
    participant Backend as Backend
    
    User->>Widget: Enters custom field values<br/>(e.g., name, email)
    Widget->>Widget: Validates required fields
    User->>Widget: Clicks submit fields button
    Widget->>API: createPayment(amount, address, fields)
    API->>Backend: POST /payment<br/>(amount, address, fields)
    Backend-->>API: Payment created (paymentId)
    API-->>Widget: Returns paymentId
    Widget->>Widget: Invokes onFieldsSubmit(fieldValues)
    Widget->>Widget: Updates state with paymentId<br/>(triggers payment UI)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • feat: regenerate paymentId when amount is updated #572: Modifies the same React components (PayButton, PaymentDialog, Widget, WidgetContainer) and extends the createPayment function, adding interconnected props/parameters to the component hierarchy.
  • fix: many fixes and tests. #592: Updates createPayment usage and paymentId creation/flow which directly relates to the field submission integration and payment creation pathway in this PR.

Suggested labels

enhancement (behind the scenes)

Suggested reviewers

  • chedieck

Poem

🐰 Fields now flow like carrots in a row,
Through components dancing high and low,
Validation checks and values tight,
Custom forms make widgets bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides a basic explanation and references issue #66, but the test plan lacks specificity and contains a typo ('everythin'), and the description content is minimal compared to the template structure. Expand the description with implementation details and improve the test plan by specifying exact steps, pages to visit, and validation criteria for verifying the fields functionality.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: fields prop' is concise and directly summarizes the main feature addition, though it could be slightly more specific about what the feature enables.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lissavxo lissavxo changed the title feat: fields param feat: fields prop Jan 14, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@docs/README.md`:
- Around line 1130-1163: Add documentation for the missing on-fields-submit
callback: explain that the 'on-fields-submit' parameter (also exposed as
onFieldsSubmit in JS/React) is optional and accepts a function invoked when
custom fields are submitted; document the callback argument fieldValues (object
of fieldName => value) and include short examples for HTML (string handler
name), JavaScript (onFieldsSubmit: (fieldValues) => {...}) and React
(onFieldsSubmit = {(fieldValues) => {...}}) mirroring the style used for the
'fields' section and place it immediately after the existing 'fields' section.

In `@react/lib/components/Widget/Widget.tsx`:
- Around line 667-668: Remove the stray debug console.log("entrou aqui carai")
from the Widget component; keep the setPaymentId(responsePaymentId) call intact
(i.e., delete the console.log statement near setPaymentId in Widget.tsx so no
debug output with non-English text remains).
- Around line 1014-1028: Remove the debug console.log call inside the payment
creation try block: delete the line that logs "{ newPaymentId, setPaymentId }"
after calling createPayment(effectiveAmount, to, apiBaseUrl, fieldsWithValues).
Ensure the rest of the flow that checks setPaymentId and calls
setOpReturn(encodeOpReturnProps(...)) and setPaymentId(newPaymentId) remains
unchanged so behavior with disablePaymentId,
convertedCryptoAmount/thisCurrencyObject?.float, props.opReturn, and setOpReturn
is preserved.
- Around line 987-993: The snippet in Widget.tsx contains a debug console.log
call inside the callback that sets copied state (the callback using setCopied
and setRecentlyCopied with dependencies [disabled, to, url, setCopied,
setRecentlyCopied, qrLoading, paymentId]); remove the console.log({ url,
paymentId }) statement so no debug output is emitted in production, and ensure
no other stray console.debug/console.log calls remain in the same function or
nearby callbacks (keep only necessary logging via the app's logger if required).
🧹 Nitpick comments (6)
paybutton/dev/demo/index.html (1)

33-39: Demo addition looks good.

The new PayButton example correctly demonstrates the fields feature with proper JSON syntax. The field object includes the required properties (name, text, type).

Consider also adding an on-fields-submit callback to demonstrate how to handle the submitted field values:

on-fields-submit="myFieldsSubmitCallback"

And a corresponding handler function in the script section:

function myFieldsSubmitCallback(fieldValues) {
  console.log('Fields submitted:', fieldValues);
}
react/lib/util/types.ts (1)

160-167: Field type definition is well-structured.

The new Field type correctly defines the schema for custom input fields with appropriate required and optional properties. The design is clean and aligns with standard HTML input attributes.

One consideration: the type property is currently string, which is flexible but provides no type safety. If you want to constrain it to valid HTML input types, you could use a union type:

type InputType = 'text' | 'email' | 'number' | 'tel' | 'url' | 'password' | 'date' | 'time';

export type Field = {
  name: string
  text: string
  type: InputType
  value?: string
  required?: boolean
}

However, keeping it as string allows for future extensibility with custom input types, so the current approach is also valid.

paybutton/src/index.tsx (1)

109-109: Consider adding JSON parsing for the fields attribute to match the theme pattern.

The fields prop is added to allowedProps (line 109), but unlike theme (lines 214-220), there's no JSON parsing when reading the fields attribute from DOM elements. The Widget component accepts fields?: Field[] | string, supporting both formats, but adding explicit JSON parsing here would maintain consistency with how other complex properties like theme are handled.

♻️ Suggested parsing logic (optional)
      if (attributes.theme) {
        try {
          props.theme = JSON.parse(attributes.theme)
        } catch {
          // Keep the original string assignment
        }
      }
+
+     if (attributes.fields) {
+       try {
+         props.fields = JSON.parse(attributes.fields)
+       } catch {
+         // Keep the original string assignment
+       }
+     }

      if (!requiredProps.every(name => name in attributes)) {
react/lib/components/Widget/Widget.tsx (3)

1402-1441: Use field.name as key instead of array index for stable React keys.

Using the array index as a key can cause issues with React's reconciliation if fields are reordered or filtered. Since field.name is a unique identifier per the Field type definition, it should be used as the key.

Proposed fix
               {fields.map((field, index) => (
                 <TextField
-                  key={index}
+                  key={field.name}
                   label={field.text}

995-1043: Consider removing unused paymentId from dependency array.

The paymentId variable is included in the dependency array of handleFieldsSubmit but is not used within the callback body. This won't cause bugs but is inconsistent.

Proposed fix
-  }, [fields, fieldValues, success, isSubmitting, onFieldsSubmit, disablePaymentId, to, convertedCryptoAmount, thisCurrencyObject, apiBaseUrl, setPaymentId, paymentId, props.opReturn]);
+  }, [fields, fieldValues, success, isSubmitting, onFieldsSubmit, disablePaymentId, to, convertedCryptoAmount, thisCurrencyObject, apiBaseUrl, setPaymentId, props.opReturn]);

192-204: Fields JSON parsing silently discards invalid input.

When fieldsProp is a malformed JSON string, the parsing returns undefined without any user feedback. Consider logging a warning in development to help debug configuration issues.

Proposed enhancement
       if (typeof fieldsProp === 'string') {
         try {
           const parsed = JSON.parse(fieldsProp);
           return Array.isArray(parsed) ? parsed : undefined;
-        } catch {
+        } catch (e) {
+          if (process.env.NODE_ENV === 'development') {
+            console.warn('Failed to parse fields JSON:', e);
+          }
           return undefined;
         }
       }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6aa63f9 and fe2d4dc.

📒 Files selected for processing (11)
  • docs/README.md
  • docs/zh-cn/README.md
  • docs/zh-tw/README.md
  • paybutton/dev/demo/index.html
  • paybutton/src/index.tsx
  • react/lib/components/PayButton/PayButton.tsx
  • react/lib/components/PaymentDialog/PaymentDialog.tsx
  • react/lib/components/Widget/Widget.tsx
  • react/lib/components/Widget/WidgetContainer.tsx
  • react/lib/util/api-client.ts
  • react/lib/util/types.ts
🧰 Additional context used
🧬 Code graph analysis (5)
react/lib/components/PayButton/PayButton.tsx (1)
react/lib/util/types.ts (1)
  • Field (161-167)
react/lib/components/PaymentDialog/PaymentDialog.tsx (1)
react/lib/util/types.ts (1)
  • Field (161-167)
react/lib/components/Widget/Widget.tsx (2)
react/lib/util/types.ts (1)
  • Field (161-167)
react/lib/util/api-client.ts (1)
  • createPayment (94-115)
react/lib/components/Widget/WidgetContainer.tsx (1)
react/lib/util/types.ts (1)
  • Field (161-167)
react/lib/util/api-client.ts (1)
react/lib/util/types.ts (1)
  • Field (161-167)
🪛 markdownlint-cli2 (0.18.1)
docs/zh-cn/README.md

1134-1134: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)


1134-1134: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1134-1134: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1140-1140: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1140-1140: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1149-1149: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1149-1149: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1165-1165: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)


1172-1172: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1172-1172: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1178-1178: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1178-1178: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1187-1187: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1187-1187: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

docs/README.md

1134-1134: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)


1134-1134: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1134-1134: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1140-1140: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1140-1140: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1149-1149: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


1149-1149: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run build
🔇 Additional comments (9)
docs/zh-cn/README.md (1)

1129-1199: Documentation for fields and on-fields-submit looks complete.

The new documentation sections correctly describe the fields parameter with its properties (name, text, type, value, required) and the on-fields-submit callback. The examples across HTML, JavaScript, and React are consistent.

Note: The static analysis flagged heading level issues (h4 after h2), but this pattern is consistent with other callback sections in this document (e.g., on-success, on-transaction), so no change is needed.

react/lib/util/api-client.ts (1)

94-114: LGTM - Fields parameter correctly integrated into createPayment.

The optional fields parameter is cleanly added to the function signature and payload. The implementation is backward-compatible since fields is optional.

Note: Ensure server-side validation handles malformed or malicious field data, as no client-side sanitization is performed before sending.

docs/zh-tw/README.md (1)

1125-1194: Documentation is well-structured and comprehensive.

The new fields and on-fields-submit parameter documentation follows the existing documentation patterns and provides clear examples in all three formats (HTML, JavaScript, React). The field object structure and callback signature are accurately documented.

react/lib/components/Widget/WidgetContainer.tsx (1)

22-22: LGTM - Fields prop correctly threaded through WidgetContainer.

The fields prop is properly imported, typed, destructured, and forwarded to the Widget component. The implementation maintains consistency with the component hierarchy.

Also applies to: 58-58, 143-143, 333-333

react/lib/components/PaymentDialog/PaymentDialog.tsx (1)

6-6: LGTM - Fields prop correctly integrated into PaymentDialog.

The fields prop is properly imported, added to the interface, destructured, and forwarded to WidgetContainer. The implementation maintains consistency with the component chain.

Also applies to: 70-70, 133-135, 264-264

react/lib/components/PayButton/PayButton.tsx (4)

23-24: LGTM!

Imports are appropriate—createPayment is used in getPaymentId and Field is used for the new prop type.


63-63: LGTM!

The optional fields prop is correctly typed and follows the existing prop patterns.


91-91: LGTM!

Prop destructuring is correct. Leaving fields as potentially undefined is acceptable since it's optional.


470-470: The code is correct—no changes needed.

The fields prop is properly forwarded through PaymentDialog to the Widget component. The fields are not passed to createPayment at line 154 in PayButton because they contain no user values at that point—they are empty templates.

The intended flow is:

  1. PayButton creates an initial payment ID without field values (line 154)
  2. PaymentDialog opens, and Widget renders field inputs for the user to fill
  3. When the user submits the form, Widget.tsx:1017 calls createPayment with the populated field values (fieldsWithValues)

This design allows the payment ID to be created immediately while still accommodating user-provided field data when it becomes available.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +1130 to +1163
## fields

> **The 'fields' parameter specifies custom input fields to collect additional information from users before payment.**
?> This parameter is optional. Default value is empty. Possible values are an array of field objects or a JSON string. Each field object can have the following properties: `name` (required, unique identifier), `text` (required, label displayed to user), `type` (input type like 'text', 'email', 'number'), `value` (default value), and `required` (boolean).

**Example:**
<!-- tabs:start -->

#### ** HTML **

```html
fields='[{"name": "email", "text": "Email Address", "type": "email", "required": true}, {"name": "note", "text": "Note", "type": "text"}]'
```

#### ** JavaScript **

```javascript
fields: [
{ name: 'email', text: 'Email Address', type: 'email', required: true },
{ name: 'note', text: 'Note', type: 'text' }
]
```

#### ** React **

```react
fields = {[
{ name: 'email', text: 'Email Address', type: 'email', required: true },
{ name: 'note', text: 'Note', type: 'text' }
]}
```
<!-- tabs:end -->

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing on-fields-submit callback documentation.

The fields parameter documentation is well-written, but the English documentation is missing the on-fields-submit callback section that exists in the Chinese version (docs/zh-cn/README.md lines 1163-1198). Users need to know about this callback to handle field submissions.

📝 Suggested addition after line 1163
## on-fields-submit

> **The 'on-fields-submit' parameter specifies the callback function that runs when users submit custom fields.**

?> This parameter is optional. Default value is empty. Possible values are any defined function.

#### *callback* arguments

- **fieldValues** (`object`): An object containing field values keyed by field name

**Example:**
<!-- tabs:start -->

#### ** HTML **

```html
on-fields-submit="fieldsSubmitCallback"

** JavaScript **

onFieldsSubmit: (fieldValues) => {
  console.log('Fields submitted:', fieldValues);
  // fieldValues example: { email: 'user@example.com', note: 'My payment note' }
}

** React **

onFieldsSubmit = {(fieldValues) => {
  console.log('Fields submitted:', fieldValues);
}}
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

1134-1134: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

---

1134-1134: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

---

1134-1134: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

---

1140-1140: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

---

1140-1140: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

---

1149-1149: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

---

1149-1149: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In @docs/README.md around lines 1130 - 1163, Add documentation for the missing
on-fields-submit callback: explain that the 'on-fields-submit' parameter (also
exposed as onFieldsSubmit in JS/React) is optional and accepts a function
invoked when custom fields are submitted; document the callback argument
fieldValues (object of fieldName => value) and include short examples for HTML
(string handler name), JavaScript (onFieldsSubmit: (fieldValues) => {...}) and
React (onFieldsSubmit = {(fieldValues) => {...}}) mirroring the style used for
the 'fields' section and place it immediately after the existing 'fields'
section.


</details>

<!-- fingerprinting:phantom:poseidon:ocelot -->

<!-- This is an auto-generated comment by CodeRabbit -->

@lissavxo lissavxo force-pushed the feat/arbitrary-fields branch from fe2d4dc to e8969f5 Compare January 14, 2026 23:11
@lissavxo lissavxo force-pushed the feat/arbitrary-fields branch from e8969f5 to 9cab186 Compare January 14, 2026 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants