Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,7 @@ private FormConstants() {
/** The resource type for date time input field v1 */
public static final String RT_FD_FORM_DATETIME_V1 = RT_FD_FORM_PREFIX + "datetime/v1/datetime";

/** The resource type for Adobe Sign Block v1 */
public static final String RT_FD_FORM_ADOBE_SIGN_BLOCK_V1 = RT_FD_FORM_PREFIX + "adobesignblock/v1/adobesignblock";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Copyright 2026 Adobe
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
package com.adobe.cq.forms.core.components.internal.models.v1.form;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Exporter;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import com.adobe.cq.export.json.ComponentExporter;
import com.adobe.cq.export.json.ExporterConstants;
import com.adobe.cq.forms.core.components.internal.form.FormConstants;
import com.adobe.cq.forms.core.components.models.form.Base;
import com.adobe.cq.forms.core.components.models.form.FieldType;
import com.adobe.cq.forms.core.components.models.form.Text;
import com.adobe.cq.forms.core.components.util.AbstractBaseImpl;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;

/**
* Sling Model for the Adobe Sign Block core component.
*
* <p>
* Extends {@link AbstractBaseImpl} (same base as all other form field components) so it participates correctly in
* form-model serialisation and test casting. Implements the {@link Text} interface — replicating the rich-text value
* and fieldType behaviour from {@link TextImpl} — while inheriting:
* </p>
* <ul>
* <li>{@code getLabel()} from {@link AbstractBaseImpl}: builds a {@code LabelImpl} from {@code jcr:title} and
* {@code hideTitle}, putting the authored title into the component's JSON model so the form engine and Rules Engine can
* update it.</li>
* <li>{@code getDataRef()} from {@link com.adobe.cq.forms.core.components.util.AbstractFormComponentImpl}: serialises
* the {@code dataRef} JCR property into the JSON model, wiring up the bind-reference backend.</li>
* </ul>
*/
@Model(
adaptables = { SlingHttpServletRequest.class, Resource.class },
adapters = { Text.class, Base.class,
ComponentExporter.class },
resourceType = { FormConstants.RT_FD_FORM_ADOBE_SIGN_BLOCK_V1 })
@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION)
public class AdobeSignBlockImpl extends AbstractBaseImpl implements Text {

private static final Pattern ADOBE_SIGN_TAG_PATTERN = Pattern.compile("\\{\\{[*]?([^:]*)_es_:");

/**
* The Adobe Sign merge-tag markup (e.g. {@code <span data-adobesigntype="signature">
* {{fieldName_es_:signer1:signature}}</span>}), computed client-side by editDialog.js reusing
* integration-adobesign's own dialog plugin ({@code getDomContentFromDialog()} /
* {@code ADOBESIGN_UTILS.getDomContent()}) from the included Type/Name/Options/etc. field set,
* rather than reimplemented here.
*/
@ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL)
private String adobeSignFieldTag;

/**
* Combines the author's narrative {@code value} text - always authored as rich text, there is no
* plain-text mode for this field - with the client-computed {@link #adobeSignFieldTag}, so
* downstream DoR/agreement generation sees the same wire format it always has, regardless of how the
* field was authored. Never wrapped in an artificial {@code <p>} — the narrative can already contain
* its own block-level markup (lists, paragraphs), and nesting that inside a single forced {@code <p>}
* produces invalid HTML that corrupts the author-canvas DOM.
*/
@Override
public String getValue() {
String tag = StringUtils.defaultString(adobeSignFieldTag);
String markup = StringUtils.isNotBlank(value) ? value + "&nbsp;" + tag : tag;
return translate("value", markup);
}

/**
* Always {@code true}: the Text field is always authored as rich text, and the rendered value
* always additionally contains the real (unescaped) placeholder markup above.
*/
@Override
public boolean isRichText() {
return true;
}

/**
* Excluded from JSON; the rich-text content is surfaced via {@link #getValue()}.
*/
@Override
@JsonIgnore
public String getText() {
return getValue();
}

@Override
public String getFieldType() {
return FieldType.ADOBE_SIGN_BLOCK.getValue();
}

/**
* Returns the names of Adobe Sign text-tag fields embedded in this block's HTML content
* (e.g. {@code {{Signature1_es_:signer1:signature}}} yields {@code "Signature1"}).
* Returns {@code null} when no text tags are present so the property is omitted from JSON.
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public String[] getAdobeSignFields() {
String blockValue = getValue();
if (blockValue != null && !blockValue.isEmpty()) {
List<String> fieldNames = new ArrayList<>();
Set<String> seen = new HashSet<>();
Matcher matcher = ADOBE_SIGN_TAG_PATTERN.matcher(blockValue);
while (matcher.find()) {
String fieldName = matcher.group(1);
if (seen.add(fieldName)) {
fieldNames.add(fieldName);
}
}
if (!fieldNames.isEmpty()) {
return fieldNames.toArray(new String[0]);
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum FieldType {
DROP_DOWN("drop-down"),
RADIO_GROUP("radio-group"),
PLAIN_TEXT("plain-text"),
ADOBE_SIGN_BLOCK("adobe-sign-block"),
CHECKBOX("checkbox"),
BUTTON("button"),
PANEL("panel"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Component"
jcr:title="Adaptive Form Adobe Sign Block"
jcr:description="Add an Adobe Sign block to capture signatures and other signer inputs."
sling:resourceSuperType="core/fd/components/form/adobesignblock/v1/adobesignblock"
componentGroup="Core Components Examples - Adaptive Form"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Adobe Sign Block"
fieldType="adobe-sign-block"
value="Signature:"
adobeSignFieldTag="&lt;span data-adobesigntype=&quot;signature&quot;&gt;{{sampleField_es_:signer1:signature}}&lt;/span&gt;"
visible="{Boolean}false"/>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
jcr:primaryType="nt:unstructured"
jcr:title="Core Components Examples - Root"
sling:resourceType="wcm/core/components/policy/policy"
components="[/libs/wcm/foundation/components/responsivegrid,group:Core Components Examples,group:.core-wcm,group:.core-wcm-form,group:Core Components Examples - Adaptive Form,group:Core Components Examples - Forms And Communications Portal]">
components="[/libs/wcm/foundation/components/responsivegrid,group:Core Components Examples,group:.core-wcm,group:.core-wcm-form,group:Core Components Examples - Adaptive Form,group:Core Components Examples - Forms And Communications Portal,group:Adobe Sign - Adaptive Form]">
<cq:authoring jcr:primaryType="nt:unstructured">
<assetToComponentMapping jcr:primaryType="nt:unstructured">
<mapping_1544531934044
Expand Down Expand Up @@ -131,7 +131,7 @@
jcr:primaryType="nt:unstructured"
jcr:title="formcontainer-policy"
sling:resourceType="wcm/core/components/policy/policy"
components="[group:Core Components Examples - Adaptive Form,group:Core Components Examples - Forms And Communications Portal]">
components="[group:Core Components Examples - Adaptive Form,group:Core Components Examples - Forms And Communications Portal,group:Adobe Sign - Adaptive Form]">
<jcr:content jcr:primaryType="nt:unstructured"/>
</policy_212634895490171>
</container>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:rep="internal"
jcr:mixinTypes="[rep:AccessControllable]"
jcr:primaryType="sling:Folder"
hidden="true"/>
3 changes: 3 additions & 0 deletions ui.af.apps/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@
<exclude>**/node_modules/**</exclude>
<!-- Ignore generated datalayer clientlib -->
<exclude>**/core.wcm.components.commons.datalayer.v1/**</exclude>
<!-- Ignore auto-generated runtime clientlibs (see .gitignore) -->
<exclude>**/core-forms-components-runtime-base/**</exclude>
<exclude>**/core-forms-components-runtime-base-xfa/**</exclude>
</excludes>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:ClientLibraryFolder"
allowProxy="{Boolean}true"
categories="[core.forms.components.adobesign.placeholder,cq.authoring.editor.forms,cq.authoring.editor.forms.v2]"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#base=css
adobesignplaceholder.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright 2026 Adobe
*
* Global Adobe Sign placeholder styles for the Forms v2 editor and in-place RTE.
* Matches foundation fd/afaddon/adobesign/common (guide.theme2.common).
* Must be global — RTE and authoring overlays are not under .cmp-adaptiveform-adobesignblock__value.
******************************************************************************/

[data-adobesigntype]::selection {
color: rgba(0, 0, 0, 0);
}

[data-adobesigntype]::-moz-selection {
color: rgba(0, 0, 0, 0);
}

[data-adobesigntype] {
width: 6rem;
display: inline-block;
color: rgba(0, 0, 0, 0);
border-bottom-style: solid;
border-bottom-width: 1px;
border-bottom-color: rgba(0, 0, 0, 0.3);
margin-left: 0.5rem;
margin-right: 0.5rem;
white-space: nowrap;
overflow: hidden;
cursor: pointer;
}

[data-adobesigntype='radio'],
[data-adobesigntype='checkbox'] {
border-bottom-width: 0;
background-repeat: no-repeat;
background-position: left center;
width: 3rem;
min-height: 10px;
}

[data-adobesigntype='radio'] {
background-image: url(../resources/images/radiobutton.svg);
}

[data-adobesigntype='checkbox'] {
background-image: url(../resources/images/checkbox.svg);
}

[data-adobesigntype='dropdown'] {
background-image: url(../resources/images/dropdown_chevron.svg);
background-repeat: no-repeat;
background-position: right center;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
cssProcessor="[default:none,min:none]"
jsProcessor="[default:none,min:none]"
categories="[core.forms.components.runtime.all]"
embed="[core.forms.components.runtime.base,core.forms.components.container.v2.runtime,core.forms.components.datePicker.v1.runtime,core.forms.components.textinput.v1.runtime,core.forms.components.numberinput.v1.runtime,core.forms.components.panelcontainer.v1.runtime,core.forms.components.radiobutton.v2.runtime,core.forms.components.text.v1.runtime,core.forms.components.checkboxgroup.v1.runtime,core.forms.components.button.v1.runtime,core.forms.components.image.v1.runtime,core.forms.components.dropdown.v1.runtime,core.forms.components.fileinput.v4.runtime,core.forms.components.accordion.v1.runtime,core.forms.components.tabs.v1.runtime,core.forms.components.wizard.v1.runtime,core.forms.components.verticaltabs.v1.runtime,core.forms.components.recaptcha.v1.runtime,core.forms.components.checkbox.v1.runtime,core.forms.components.fragment.v1.runtime,core.forms.components.switch.v1.runtime,core.forms.components.termsandconditions.v1.runtime,core.forms.components.review.v1.runtime,core.forms.components.scribble.v1.runtime,core.forms.components.datetime.v1.runtime]"/>
embed="[core.forms.components.runtime.base,core.forms.components.container.v2.runtime,core.forms.components.datePicker.v1.runtime,core.forms.components.textinput.v1.runtime,core.forms.components.numberinput.v1.runtime,core.forms.components.panelcontainer.v1.runtime,core.forms.components.radiobutton.v2.runtime,core.forms.components.text.v1.runtime,core.forms.components.checkboxgroup.v1.runtime,core.forms.components.button.v1.runtime,core.forms.components.image.v1.runtime,core.forms.components.dropdown.v1.runtime,core.forms.components.fileinput.v4.runtime,core.forms.components.accordion.v1.runtime,core.forms.components.tabs.v1.runtime,core.forms.components.wizard.v1.runtime,core.forms.components.verticaltabs.v1.runtime,core.forms.components.recaptcha.v1.runtime,core.forms.components.checkbox.v1.runtime,core.forms.components.fragment.v1.runtime,core.forms.components.switch.v1.runtime,core.forms.components.termsandconditions.v1.runtime,core.forms.components.review.v1.runtime,core.forms.components.scribble.v1.runtime,core.forms.components.datetime.v1.runtime,core.forms.components.adobesignblock.v1.runtime]"/>
Loading
Loading