Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] React example for do not sell button #46

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
74 changes: 74 additions & 0 deletions src/DoNotSellButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* eslint-disable no-restricted-globals */

import { AirgapAPI, TranscendAPI } from '@transcend-io/airgap.js-types';
import { h, FunctionComponent } from 'preact';
import { useEffect, useState } from 'preact/hooks';

/**
* Global window with airgap instance attached
*/
type WindowWithAirgap = typeof self & {
/** Airgap instance should have been initialized on self when script added in header */
transcend: TranscendAPI;
/** Airgap API */
airgap: AirgapAPI;
};

/**
* A button that implements the logic for Do Not Sell/Do Not Share
* to ensure compliance with laws like CPRA, CPA, CDPA
*/
export const DoNotSellButton: FunctionComponent = () => {
// Ensure airgap was initialized
const selfWithAirgap = self as WindowWithAirgap;
if (!selfWithAirgap.airgap || !selfWithAirgap.transcend) {
throw new Error(`Expected airgap and transcend to be initialized on self!`);
}

// Check if the user is opted into sale of data
const [isSellingData, setIsSellingData] = useState(
!!selfWithAirgap.airgap.getConsent().purposes.SaleOfInfo,
);

// update state variable when consent values change
useEffect(() => {
// Callback to re-calculate consent preferences
const onConsentChange = (): void => {
setIsSellingData(
!!selfWithAirgap.airgap.getConsent().purposes.SaleOfInfo,
);
};

// Add listener on change to re-calculate consent preferences
selfWithAirgap.airgap.addEventListener('consent-change', onConsentChange);

// Remove event listener when component dismounts
return () =>
selfWithAirgap.airgap.removeEventListener(
'consent-change',
onConsentChange,
);
}, [selfWithAirgap.airgap]);

// Only show the button in california
if (!selfWithAirgap.airgap.getRegimes().has('CPRA')) {
return null;
}

return (
<button
onClick={
// only open modal if user is currently opted out
isSellingData
? (event) => selfWithAirgap.transcend.doNotSell(event.nativeEvent)
: undefined
}
disabled={!isSellingData}
>
{isSellingData
? 'Do Not Sell My Personal Information'
: 'We No Longer Sell Your Personal Information'}
</button>
);
};
/* eslint-enable no-restricted-globals */