Skip to content
Merged
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
32 changes: 32 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copilot Instructions for ENgrid

## High-Level Architecture
- ENgrid is a Lerna workspace with two publishable packages: `packages/scripts` (TypeScript) and `packages/styles` (SCSS). Only edit the sources; `dist/` artifacts are generated.
- `packages/scripts/src/app.ts` orchestrates runtime features by instantiating helpers exported via `packages/scripts/src/index.ts`.
- `ENGrid` (`packages/scripts/src/engrid.ts`) centralizes DOM helpers, Engaging Networks integrations, and shared utilities (URL params, field setters, body data attributes).
- Front-end behaviour is driven by Engaging Networks globals (`window.pageJson`, `window.EngagingNetworks`, `window.EngridOptions`) and data attributes stamped on `<body>`.

## Key Workflows
- Install dependencies once with `npm install` at repo root; Lerna bootstraps package links.
- Build everything via `npm run build` (runs `lerna bootstrap` then `lerna run build`), or watch with `npm run watch` (`lerna run watch`).
- Within a package you can run `npm run watch` to recompile just scripts (tsc via nodemon) or styles (sass via nodemon).
- Version bumps rely on `npm run version`, which executes `write-version.js` to sync `AppVersion` and then rebuilds.

## Patterns & Conventions
- Globals are hung off `window.EngridOptions`; override per page through `window.EngridPageOptions` before `new App(...)` runs.
- Features toggle themselves by checking DOM/body data attributes (`data-engrid-*`). For example, `digital-wallets.ts` only defaults Stripe wallets when `data-engrid-payment-type-option-*="true"`.
- Evented logic uses singletons in `packages/scripts/src/events` (e.g., `DonationAmount.getInstance()`); prefer extending those patterns over ad-hoc listeners.
- Styles aggregate through `packages/styles/src/main.scss`, which imports feature partials (digital wallets, tidycontact, etc.) and layout themes under `packages/styles/src/themes/`.

## Integration Notes
- Loader behaviour (`packages/scripts/src/loader.ts`) swaps CSS/JS assets based on `window.EngridLoader` or URL flags like `?assets=local&engridcss=false`; respect this when altering bootstrapping.
- Use helpers from the `ENGrid` abstract class (`packages/scripts/src/engrid.ts`) where possible.
- Many helpers expect the Engaging Networks form markup (`form.en__component`); use `ENGrid.checkNested` or guard early when working outside that environment.
- Client-specific repos in sibling folders consume the built assets; keep shared business logic in core packages unless a customization truly belongs downstream.
- Tip: when debugging, `?debug=true` sets body `data-engrid-debug`, unlocking debug panels and conditional UI.

## When in Doubt
- Search in `packages/scripts/src` before creating new utilities; most EN behaviours already exist (currency, remember-me, plaid, vgs).
- Do not hand-edit files under any `dist/` directory—run the relevant build instead.
- Follow repo Prettier config (`.prettierrc.js`); formatting is enforced even though there are no automated tests.
- Document new options by updating the interfaces in `packages/scripts/src/interfaces` and exposing them through `OptionsDefaults`.
3 changes: 2 additions & 1 deletion packages/scripts/dist/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DonationAmount, DonationFrequency, EnForm, ProcessingFees, Country, } from "./events";
import { AmountLabel, Loader, ProgressBar, UpsellLightbox, ENGrid, OptionsDefaults, setRecurrFreq, PageBackground, MediaAttribution, ApplePay, A11y, CapitalizeFields, Ecard, ClickToExpand, Advocacy, DataAttributes, LiveVariables, iFrame, InputPlaceholders, InputHasValueAndFocus, ShowHideRadioCheckboxes, AutoCountrySelect, SkipToMainContentLink, SrcDefer, NeverBounce, AutoYear, Autocomplete, RememberMe, TranslateFields, ShowIfAmount, EngridLogger, OtherAmount, MinMaxAmount, Ticker, DataReplace, DataHide, AddNameToMessage, ExpandRegionName, AppVersion, UrlToForm, RequiredIfVisible, TidyContact, DataLayer, LiveCurrency, Autosubmit, EventTickets, SwapAmounts, DebugPanel, DebugHiddenFields, FreshAddress, BrandingHtml, CountryDisable, PremiumGift, DigitalWallets, MobileCTA, LiveFrequency, UniversalOptIn, Plaid, GiveBySelect, UrlParamsToBodyAttrs, ExitIntentLightbox, SupporterHub, FastFormFill, SetAttr, ShowIfPresent, ENValidators, CustomCurrency, VGS, PostalCodeValidator, CountryRedirect, WelcomeBack, EcardToTarget, UsOnlyForm, ThankYouPageConditionalContent, EmbeddedEcard, CheckboxLabel, UpsellCheckbox, PostDonationEmbed, FrequencyUpsell, CustomPremium, } from ".";
import { AmountLabel, Loader, ProgressBar, UpsellLightbox, ENGrid, OptionsDefaults, setRecurrFreq, PageBackground, MediaAttribution, ApplePay, A11y, CapitalizeFields, Ecard, ClickToExpand, Advocacy, DataAttributes, LiveVariables, iFrame, InputPlaceholders, InputHasValueAndFocus, ShowHideRadioCheckboxes, AutoCountrySelect, SkipToMainContentLink, SrcDefer, NeverBounce, AutoYear, Autocomplete, RememberMe, TranslateFields, ShowIfAmount, EngridLogger, OtherAmount, MinMaxAmount, Ticker, DataReplace, DataHide, AddNameToMessage, ExpandRegionName, AppVersion, UrlToForm, RequiredIfVisible, TidyContact, DataLayer, LiveCurrency, Autosubmit, EventTickets, SwapAmounts, DebugPanel, DebugHiddenFields, FreshAddress, BrandingHtml, CountryDisable, PremiumGift, DigitalWallets, MobileCTA, LiveFrequency, UniversalOptIn, Plaid, GiveBySelect, UrlParamsToBodyAttrs, ExitIntentLightbox, SupporterHub, FastFormFill, SetAttr, ShowIfPresent, ENValidators, CustomCurrency, VGS, PostalCodeValidator, CountryRedirect, WelcomeBack, EcardToTarget, UsOnlyForm, ThankYouPageConditionalContent, EmbeddedEcard, CheckboxLabel, UpsellCheckbox, PostDonationEmbed, FrequencyUpsell, CustomPremium, PreferredPaymentMethod, } from ".";
export class App extends ENGrid {
constructor(options) {
super();
Expand Down Expand Up @@ -253,6 +253,7 @@ export class App extends ENGrid {
// Digital Wallets Features
if (ENGrid.getPageType() === "DONATION") {
new DigitalWallets();
new PreferredPaymentMethod();
}
// Mobile CTA
new MobileCTA();
Expand Down
1 change: 1 addition & 0 deletions packages/scripts/dist/digital-wallets.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export declare class DigitalWallets {
private static isApplePayAvailable;
constructor();
private addStripeDigitalWallets;
private addPaypalTouchDigitalWallets;
Expand Down
8 changes: 6 additions & 2 deletions packages/scripts/dist/digital-wallets.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export class DigitalWallets {
constructor() {
//digital wallets not enabled.
if (!document.getElementById("en__digitalWallet")) {
ENGrid.setBodyData("payment-type-option-stripedigitalwallet", "false");
ENGrid.setBodyData("payment-type-option-apple-pay", "false");
ENGrid.setBodyData("payment-type-option-google-pay", "false");
ENGrid.setBodyData("payment-type-option-paypal-one-touch", "false");
Expand Down Expand Up @@ -41,6 +42,7 @@ export class DigitalWallets {
else {
ENGrid.setBodyData("payment-type-option-apple-pay", "false");
ENGrid.setBodyData("payment-type-option-google-pay", "false");
ENGrid.setBodyData("payment-type-option-stripedigitalwallet", "false");
const stripeContainer = document.getElementById("en__digitalWallet__stripeButtons__container");
if (stripeContainer) {
this.checkForWalletsBeingAdded(stripeContainer, "stripe");
Expand Down Expand Up @@ -85,8 +87,9 @@ export class DigitalWallets {
}
addStripeDigitalWallets() {
this.addOptionToPaymentTypeField("stripedigitalwallet", "GooglePay / ApplePay");
ENGrid.setBodyData("payment-type-option-apple-pay", "true");
ENGrid.setBodyData("payment-type-option-google-pay", "true");
ENGrid.setBodyData("payment-type-option-apple-pay", DigitalWallets.isApplePayAvailable.toString());
ENGrid.setBodyData("payment-type-option-google-pay", !DigitalWallets.isApplePayAvailable.toString());
ENGrid.setBodyData("payment-type-option-stripedigitalwallet", "true");
}
addPaypalTouchDigitalWallets() {
this.addOptionToPaymentTypeField("paypaltouch", "Paypal / Venmo");
Expand Down Expand Up @@ -141,3 +144,4 @@ export class DigitalWallets {
observer.observe(node, { childList: true, subtree: true });
}
}
DigitalWallets.isApplePayAvailable = !!window.hasOwnProperty("ApplePaySession");
1 change: 1 addition & 0 deletions packages/scripts/dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,6 @@ export * from "./optin-ladder";
export * from "./post-donation-embed";
export * from "./frequency-upsell-modal";
export * from "./frequency-upsell";
export * from "./preferred-payment-method";
export * from "./events";
export * from "./version";
1 change: 1 addition & 0 deletions packages/scripts/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export * from "./optin-ladder";
export * from "./post-donation-embed";
export * from "./frequency-upsell-modal";
export * from "./frequency-upsell";
export * from "./preferred-payment-method";
// Events
export * from "./events";
// Version
Expand Down
4 changes: 4 additions & 0 deletions packages/scripts/dist/interfaces/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ export interface Options {
placementQuerySelector?: string | null;
excludePageIDs?: string[];
};
PreferredPaymentMethod?: false | {
preferredPaymentMethodField?: string;
defaultPaymentMethod?: string[];
};
CustomPremium?: false | {
[frequency: string]: ({
products?: {
Expand Down
1 change: 1 addition & 0 deletions packages/scripts/dist/interfaces/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const OptionsDefaults = {
CountryRedirect: false,
WelcomeBack: false,
OptInLadder: false,
PreferredPaymentMethod: false,
PageLayouts: [
"leftleft1col",
"centerleft1col",
Expand Down
31 changes: 31 additions & 0 deletions packages/scripts/dist/preferred-payment-method.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export declare class PreferredPaymentMethod {
private logger;
private readonly availabilityTimeoutMs;
private cleanupHandlers;
private selectionFinalized;
private listenersAttached;
private config;
private preferredFieldName;
constructor();
private shouldRun;
private resolveConfig;
private buildCandidateList;
private hasPreferredField;
private attachGiveBySelectListeners;
private syncPreferredField;
private getFieldPreference;
private getUrlPreference;
private tryCandidateAtIndex;
private waitForAvailability;
private applySelection;
private paymentMethodExists;
private isPaymentMethodAvailable;
private findPaymentInput;
private getGiveBySelectInputs;
private getGiveBySelectContainer;
private getInputContainer;
private findLabelForInput;
private normalizePaymentValue;
private getAvailabilityAttributeFilters;
private cleanupAllObservers;
}
Loading
Loading