@codecademy/brand 2.5.0-alpha.975930aaa2.0 → 3.0.0-alpha.220d4ef8ba.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 (64) hide show
  1. package/dist/AppHeader/AppHeaderElements/AppHeaderCatalogSection/elements.d.ts +0 -5
  2. package/dist/AppHeader/AppHeaderElements/AppHeaderCatalogSection/elements.js +12 -56
  3. package/dist/AppHeader/AppHeaderElements/AppHeaderCatalogSection/index.js +3 -5
  4. package/dist/CareerPathCard/index.d.ts +1 -4
  5. package/dist/CareerPathCard/index.js +7 -15
  6. package/dist/CertificationPathCard/index.d.ts +1 -4
  7. package/dist/CertificationPathCard/index.js +9 -17
  8. package/dist/ContentGroupBaseCard/index.d.ts +3 -5
  9. package/dist/ContentGroupBaseCard/index.js +72 -129
  10. package/dist/ContentGroupBaseCard/shared.js +23 -29
  11. package/dist/CourseCard/index.d.ts +1 -4
  12. package/dist/CourseCard/index.js +11 -15
  13. package/dist/GlobalHeader/GlobalHeaderItems.js +1 -1
  14. package/dist/GlobalHeader/index.d.ts +0 -1
  15. package/dist/GlobalHeader/index.js +37 -41
  16. package/dist/GlobalHeader/types.d.ts +0 -1
  17. package/dist/LearningOutcomeAssessmentScores/AssessmentDetail.d.ts +8 -0
  18. package/dist/LearningOutcomeAssessmentScores/AssessmentDetail.js +55 -0
  19. package/dist/LearningOutcomeAssessmentScores/index.d.ts +8 -0
  20. package/dist/LearningOutcomeAssessmentScores/index.js +24 -0
  21. package/dist/LearningOutcomeFlyout/index.d.ts +32 -0
  22. package/dist/LearningOutcomeFlyout/index.js +170 -0
  23. package/dist/LearningOutcomeTile/index.js +1 -3
  24. package/dist/LearningOutcomeTile/types.d.ts +0 -1
  25. package/dist/SkillPathCard/index.d.ts +1 -4
  26. package/dist/SkillPathCard/index.js +7 -15
  27. package/dist/index.d.ts +2 -1
  28. package/dist/index.js +2 -1
  29. package/dist/stories/Molecules/ContentGroupBaseCard.stories.js +1 -3
  30. package/dist/stories/Molecules/CurriculumCards/CareerPathCard.stories.js +1 -3
  31. package/dist/stories/Molecules/CurriculumCards/CertificationPathCard.stories.js +1 -3
  32. package/dist/stories/Molecules/CurriculumCards/CourseCard.stories.js +1 -3
  33. package/dist/stories/Molecules/CurriculumCards/SkillPathCard.stories.js +1 -3
  34. package/dist/stories/Molecules/LearningOutcomeAssessmentScores.stories.d.ts +6 -0
  35. package/dist/stories/Molecules/LearningOutcomeAssessmentScores.stories.js +23 -0
  36. package/dist/stories/Molecules/LearningOutcomeFlyout.stories.d.ts +5 -0
  37. package/dist/stories/Molecules/LearningOutcomeFlyout.stories.js +35 -0
  38. package/package.json +1 -1
  39. package/dist/Recurly/context/NoProvider.d.ts +0 -8
  40. package/dist/Recurly/context/NoProvider.js +0 -7
  41. package/dist/Recurly/context/elements/index.d.ts +0 -26
  42. package/dist/Recurly/context/elements/index.js +0 -46
  43. package/dist/Recurly/context/elements/index.test.js +0 -88
  44. package/dist/Recurly/context/index.d.ts +0 -2
  45. package/dist/Recurly/context/index.js +0 -2
  46. package/dist/Recurly/context/recurly/index.d.ts +0 -30
  47. package/dist/Recurly/context/recurly/index.js +0 -50
  48. package/dist/Recurly/context/recurly/index.test.js +0 -63
  49. package/dist/Recurly/context/recurly/loadRecurly.d.ts +0 -6
  50. package/dist/Recurly/context/recurly/loadRecurly.js +0 -22
  51. package/dist/Recurly/context/recurly/loadRecurly.test.js +0 -57
  52. package/dist/Recurly/context/recurly/w.d.ts +0 -14
  53. package/dist/Recurly/context/recurly/w.js +0 -4
  54. package/dist/Recurly/fields/RecurlyField.d.ts +0 -9
  55. package/dist/Recurly/fields/RecurlyField.js +0 -57
  56. package/dist/Recurly/fields/elements.d.ts +0 -17
  57. package/dist/Recurly/fields/elements.js +0 -106
  58. package/dist/Recurly/fields/elements.test.js +0 -79
  59. package/dist/Recurly/fields/index.d.ts +0 -2
  60. package/dist/Recurly/fields/index.js +0 -2
  61. package/dist/Recurly/index.d.ts +0 -2
  62. package/dist/Recurly/index.js +0 -2
  63. package/dist/stories/Molecules/Recurly.stories.d.ts +0 -5
  64. package/dist/stories/Molecules/Recurly.stories.js +0 -56
@@ -1,26 +0,0 @@
1
- import type { ElementsInstance } from '@recurly/recurly-js';
2
- import { PropsWithChildren } from 'react';
3
- /**
4
- * A provider that provides the Elements instance via context.
5
- *
6
- * If used outside of a RecurlyProvider, it will throw an error.
7
- */
8
- export declare function Elements({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
9
- /**
10
- * A hook that returns the Elements instance from context.
11
- *
12
- * If used outside of an Elements provider, it will throw an error.
13
- *
14
- * Within an Elements provider:
15
- * - If used on the server, it will return undefined.
16
- * - If used on the client, it will initially return undefined and then return
17
- * the provided Elements instance once the Recurly library is loaded.
18
- *
19
- * @param options - An object to provide an alternate contextual error message
20
- * to use if one tries to use this hook outside of an Elements provider.
21
- *
22
- * @returns The Elements instance.
23
- */
24
- export declare function useElements(options?: {
25
- noProviderError?: string;
26
- }): ElementsInstance | undefined;
@@ -1,46 +0,0 @@
1
- import { createContext, useContext, useMemo } from 'react';
2
- import { NO_PROVIDER } from '../NoProvider';
3
- import { useRecurly } from '../recurly';
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- const ElementCtx = /*#__PURE__*/createContext(NO_PROVIDER);
6
-
7
- /**
8
- * A provider that provides the Elements instance via context.
9
- *
10
- * If used outside of a RecurlyProvider, it will throw an error.
11
- */
12
- export function Elements({
13
- children
14
- }) {
15
- const recurly = useRecurly({
16
- noProviderError: 'Elements must be used within a RecurlyProvider.'
17
- });
18
- const elements = useMemo(() => recurly?.Elements(), [recurly]);
19
- return /*#__PURE__*/_jsx(ElementCtx.Provider, {
20
- value: elements,
21
- children: children
22
- });
23
- }
24
-
25
- /**
26
- * A hook that returns the Elements instance from context.
27
- *
28
- * If used outside of an Elements provider, it will throw an error.
29
- *
30
- * Within an Elements provider:
31
- * - If used on the server, it will return undefined.
32
- * - If used on the client, it will initially return undefined and then return
33
- * the provided Elements instance once the Recurly library is loaded.
34
- *
35
- * @param options - An object to provide an alternate contextual error message
36
- * to use if one tries to use this hook outside of an Elements provider.
37
- *
38
- * @returns The Elements instance.
39
- */
40
- export function useElements(options) {
41
- const elements = useContext(ElementCtx);
42
- if (elements === NO_PROVIDER) {
43
- throw new Error(options?.noProviderError ?? 'useElements must be used within a Elements provider.');
44
- }
45
- return elements;
46
- }
@@ -1,88 +0,0 @@
1
- import { setupRtl } from '@codecademy/gamut-tests';
2
- import { RecurlyProvider } from '../recurly';
3
- import { Elements, useElements } from '.';
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- let mockRecurlyPromise;
6
- jest.mock('../recurly/loadRecurly', () => ({
7
- loadRecurly: () => mockRecurlyPromise
8
- }));
9
- const renderView = setupRtl(({
10
- children
11
- }) => children);
12
- const jsEventLoop = () => new Promise(r => setTimeout(r, 0));
13
- describe('Elements', () => {
14
- it('should show content before recurly loads', () => {
15
- mockRecurlyPromise = new Promise(() => {
16
- // never resolve
17
- });
18
- const {
19
- view
20
- } = renderView({
21
- children: /*#__PURE__*/_jsx(RecurlyProvider, {
22
- publicKey: "testKey",
23
- required: ['cvv', 'postal_code'],
24
- children: /*#__PURE__*/_jsx(Elements, {
25
- children: "test-content"
26
- })
27
- })
28
- });
29
- expect(view.getByText('test-content')).toBeInTheDocument();
30
- });
31
- it('should call Elements on recurly', async () => {
32
- const mockRecurly = {
33
- Elements: jest.fn()
34
- };
35
- mockRecurlyPromise = Promise.resolve(mockRecurly);
36
- renderView({
37
- children: /*#__PURE__*/_jsx(RecurlyProvider, {
38
- publicKey: "testKey",
39
- required: ['cvv', 'postal_code'],
40
- children: /*#__PURE__*/_jsx(Elements, {})
41
- })
42
- });
43
- await jsEventLoop(); // one for the Provider's useEffect to run
44
- await jsEventLoop(); // one for the subsequent re-render where useMemo runs
45
- expect(mockRecurly.Elements).toHaveBeenCalled();
46
- });
47
- });
48
- describe('useElements', () => {
49
- const Consumer = () => {
50
- try {
51
- const elements = useElements();
52
- return /*#__PURE__*/_jsx("div", {
53
- children: typeof elements
54
- });
55
- } catch {
56
- return /*#__PURE__*/_jsx("div", {
57
- children: "error"
58
- });
59
- }
60
- };
61
- it('throws an error when used without a Elements provider', () => {
62
- const {
63
- view
64
- } = renderView({
65
- children: /*#__PURE__*/_jsx(Consumer, {})
66
- });
67
- expect(view.getByText('error')).toBeInTheDocument();
68
- });
69
- it('returns null initially, then an Elements instance once Recurly loads', async () => {
70
- const mockRecurly = {
71
- Elements: () => ({})
72
- };
73
- mockRecurlyPromise = Promise.resolve(mockRecurly);
74
- const {
75
- view
76
- } = renderView({
77
- children: /*#__PURE__*/_jsx(RecurlyProvider, {
78
- publicKey: "testKey",
79
- required: ['cvv', 'postal_code'],
80
- children: /*#__PURE__*/_jsx(Elements, {
81
- children: /*#__PURE__*/_jsx(Consumer, {})
82
- })
83
- })
84
- });
85
- expect(view.getByText('undefined')).toBeInTheDocument();
86
- expect(await view.findByText('object')).toBeInTheDocument();
87
- });
88
- });
@@ -1,2 +0,0 @@
1
- export * from './recurly';
2
- export * from './elements';
@@ -1,2 +0,0 @@
1
- export * from './recurly';
2
- export * from './elements';
@@ -1,30 +0,0 @@
1
- import type { Recurly } from '@recurly/recurly-js';
2
- import { PropsWithChildren } from 'react';
3
- import { RecurlyConfig } from './loadRecurly';
4
- export type RecurlyProviderProps = PropsWithChildren<RecurlyConfig>;
5
- /**
6
- * A provider that:
7
- * - loads the Recurly library
8
- * - ensures that only a single instance of the library is loaded
9
- * - configures the library with the provided public key
10
- * - provides the library instance via context
11
- */
12
- export declare function RecurlyProvider({ children, ...config }: RecurlyProviderProps): import("react/jsx-runtime").JSX.Element;
13
- /**
14
- * A hook that returns the Recurly instance from context.
15
- *
16
- * If used outside of a RecurlyProvider, it will throw an error.
17
- *
18
- * Within a RecurlyProvider:
19
- * - If used on the server, it will return undefined.
20
- * - If used on the client, it will initially return undefined and then return
21
- * the provided Recurly instance once it is loaded.
22
- *
23
- * @param options - An object to provide an alternate contextual error message
24
- * to use if one tries to use this hook outside of a RecurlyProvider.
25
- *
26
- * @returns The Recurly instance.
27
- */
28
- export declare function useRecurly(options?: {
29
- noProviderError?: string;
30
- }): Recurly | undefined;
@@ -1,50 +0,0 @@
1
- import { createContext, useContext, useEffect, useState } from 'react';
2
- import { NO_PROVIDER } from '../NoProvider';
3
- import { loadRecurly } from './loadRecurly';
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- const RecurlyCtx = /*#__PURE__*/createContext(NO_PROVIDER);
6
- /**
7
- * A provider that:
8
- * - loads the Recurly library
9
- * - ensures that only a single instance of the library is loaded
10
- * - configures the library with the provided public key
11
- * - provides the library instance via context
12
- */
13
- export function RecurlyProvider({
14
- children,
15
- ...config
16
- }) {
17
- const [recurly, setRecurly] = useState(undefined);
18
- useEffect(() => {
19
- loadRecurly(config).then(setRecurly);
20
- // Exclude `config` dependency as it should be treated as static.
21
- // eslint-disable-next-line react-hooks/exhaustive-deps
22
- }, []);
23
- return /*#__PURE__*/_jsx(RecurlyCtx.Provider, {
24
- value: recurly,
25
- children: children
26
- });
27
- }
28
-
29
- /**
30
- * A hook that returns the Recurly instance from context.
31
- *
32
- * If used outside of a RecurlyProvider, it will throw an error.
33
- *
34
- * Within a RecurlyProvider:
35
- * - If used on the server, it will return undefined.
36
- * - If used on the client, it will initially return undefined and then return
37
- * the provided Recurly instance once it is loaded.
38
- *
39
- * @param options - An object to provide an alternate contextual error message
40
- * to use if one tries to use this hook outside of a RecurlyProvider.
41
- *
42
- * @returns The Recurly instance.
43
- */
44
- export function useRecurly(options) {
45
- const recurly = useContext(RecurlyCtx);
46
- if (recurly === NO_PROVIDER) {
47
- throw new Error(options?.noProviderError ?? 'useRecurly must be used within a RecurlyProvider');
48
- }
49
- return recurly;
50
- }
@@ -1,63 +0,0 @@
1
- import { setupRtl } from '@codecademy/gamut-tests';
2
- import { RecurlyProvider, useRecurly } from '.';
3
- import { jsx as _jsx } from "react/jsx-runtime";
4
- let mockRecurlyPromise;
5
- jest.mock('./loadRecurly', () => ({
6
- loadRecurly: () => mockRecurlyPromise
7
- }));
8
- describe('RecurlyProvider', () => {
9
- const renderView = setupRtl(RecurlyProvider);
10
- it('should show content before recurly loads', () => {
11
- mockRecurlyPromise = new Promise(() => {
12
- // never resolve
13
- });
14
- const {
15
- view
16
- } = renderView({
17
- publicKey: 'testKey',
18
- required: ['cvv', 'postal_code'],
19
- children: 'test-content'
20
- });
21
- expect(view.getByText('test-content')).toBeInTheDocument();
22
- });
23
- });
24
- describe('useRecurly', () => {
25
- const renderView = setupRtl(({
26
- children
27
- }) => children);
28
- const Consumer = () => {
29
- try {
30
- const recurly = useRecurly();
31
- return /*#__PURE__*/_jsx("div", {
32
- children: typeof recurly
33
- });
34
- } catch {
35
- return /*#__PURE__*/_jsx("div", {
36
- children: "error"
37
- });
38
- }
39
- };
40
- it('throws an error when used without a RecurlyProvider', () => {
41
- mockRecurlyPromise = Promise.resolve({});
42
- const {
43
- view
44
- } = renderView({
45
- children: /*#__PURE__*/_jsx(Consumer, {})
46
- });
47
- expect(view.getByText('error')).toBeInTheDocument();
48
- });
49
- it('returns undefined and then an instance when used inside a RecurlyProvider', async () => {
50
- mockRecurlyPromise = Promise.resolve({});
51
- const {
52
- view
53
- } = renderView({
54
- children: /*#__PURE__*/_jsx(RecurlyProvider, {
55
- publicKey: "testKey",
56
- required: ['cvv', 'postal_code'],
57
- children: /*#__PURE__*/_jsx(Consumer, {})
58
- })
59
- });
60
- expect(view.getByText('undefined')).toBeInTheDocument();
61
- expect(await view.findByText('object')).toBeInTheDocument();
62
- });
63
- });
@@ -1,6 +0,0 @@
1
- import type { Recurly } from '@recurly/recurly-js';
2
- export type RecurlyConfig = {
3
- publicKey: string;
4
- required: string[];
5
- };
6
- export declare function loadRecurly(config: RecurlyConfig): Promise<Recurly>;
@@ -1,22 +0,0 @@
1
- import { w } from './w';
2
- export function loadRecurly(config) {
3
- if (!w._recurlyPromise) {
4
- w._recurlyPromise = new Promise(resolve => {
5
- const script = w.document.createElement('script');
6
- script.src = 'https://js.recurly.com/v4/recurly.js';
7
- script.async = true;
8
- script.onload = () => {
9
- const {
10
- recurly
11
- } = w;
12
- if (!recurly) {
13
- throw new Error('Recurly was not loaded by recurly.js');
14
- }
15
- recurly.configure(config);
16
- resolve(recurly);
17
- };
18
- w.document.head.appendChild(script);
19
- });
20
- }
21
- return w._recurlyPromise;
22
- }
@@ -1,57 +0,0 @@
1
- import { loadRecurly } from './loadRecurly';
2
- const w = {};
3
- jest.mock('./w', () => ({
4
- w
5
- }));
6
- const mockConfig = {
7
- publicKey: 'test-public-key',
8
- required: ['field1', 'field2']
9
- };
10
- describe('loadRecurly', () => {
11
- let mockScript;
12
- let mockRecurly;
13
- beforeEach(() => {
14
- mockScript = {
15
- src: '',
16
- async: false,
17
- onload: null
18
- };
19
- mockRecurly = {
20
- configure: jest.fn()
21
- };
22
- w.recurly = undefined;
23
- w._recurlyPromise = undefined;
24
- w.document = {
25
- createElement: jest.fn().mockReturnValue(mockScript),
26
- head: {
27
- appendChild: jest.fn()
28
- }
29
- };
30
- });
31
- it('should create a script, load recurly, and configure it', async () => {
32
- const promise = loadRecurly(mockConfig);
33
- expect(w.document.createElement).toHaveBeenCalledWith('script');
34
- expect(mockScript.src).toBe('https://js.recurly.com/v4/recurly.js');
35
- expect(mockScript.async).toBe(true);
36
- expect(w.document.head.appendChild).toHaveBeenCalledWith(mockScript);
37
- expect(mockScript.onload).toBeDefined();
38
- w.recurly = mockRecurly;
39
- mockScript.onload?.(new Event('load'));
40
- await promise;
41
- expect(mockRecurly.configure).toHaveBeenCalledWith(mockConfig);
42
- });
43
- it('should only create one script element when called multiple times', async () => {
44
- const promises = [loadRecurly(mockConfig), loadRecurly(mockConfig), loadRecurly(mockConfig)];
45
- w.recurly = mockRecurly;
46
- mockScript.onload?.(new Event('load'));
47
-
48
- // Should always return the same promise instance
49
- expect(promises[0]).toBe(promises[1]);
50
- expect(promises[1]).toBe(promises[2]);
51
- await Promise.all(promises);
52
-
53
- // Should only create one script element
54
- expect(w.document.createElement).toHaveBeenCalledTimes(1);
55
- expect(w.document.head.appendChild).toHaveBeenCalledTimes(1);
56
- });
57
- });
@@ -1,14 +0,0 @@
1
- import type { Recurly } from '@recurly/recurly-js';
2
- type Doc = {
3
- createElement: Document['createElement'];
4
- head: {
5
- appendChild: Document['head']['appendChild'];
6
- };
7
- };
8
- export type W = {
9
- recurly?: Recurly;
10
- _recurlyPromise?: Promise<Recurly>;
11
- document: Doc;
12
- };
13
- export declare const w: W;
14
- export {};
@@ -1,4 +0,0 @@
1
- // By importing/exporting w as a window object, we can easily mock it in tests.
2
-
3
- // Exported for easy mocking
4
- export const w = window;
@@ -1,9 +0,0 @@
1
- import { InputWrapperProps } from '@codecademy/gamut';
2
- export type RecurlyFieldProps = InputWrapperProps & {
3
- label: string;
4
- };
5
- /**
6
- * A wrapper around a Recurly element (or two elements in the case of MM/YY) to
7
- * add Gamut border styling and a label.
8
- */
9
- export declare function RecurlyField({ label, children, ...props }: RecurlyFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -1,57 +0,0 @@
1
- import _styled from "@emotion/styled/base";
2
- function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
3
- import { Box, Input, Text } from '@codecademy/gamut';
4
- import { conditionalStyles, formFieldStyles } from '@codecademy/gamut/dist/Form/styles';
5
- import { theme } from '@codecademy/gamut-styles';
6
- import { useCallback, useRef } from 'react';
7
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
8
- const Slash = /*#__PURE__*/_styled("span", {
9
- target: "e1ndrvyp1",
10
- label: "Slash"
11
- })(process.env.NODE_ENV === "production" ? {
12
- name: "18v1ai1",
13
- styles: "width:0;font-family:'Suisse';transform:translate(-6px, 1px);font-size:18px"
14
- } : {
15
- name: "18v1ai1",
16
- styles: "width:0;font-family:'Suisse';transform:translate(-6px, 1px);font-size:18px/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9SZWN1cmx5L2ZpZWxkcy9SZWN1cmx5RmllbGQudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWV5QiIsImZpbGUiOiIuLi8uLi8uLi9zcmMvUmVjdXJseS9maWVsZHMvUmVjdXJseUZpZWxkLnRzeCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJveCxcbiAgSW5wdXQsXG4gIElucHV0V3JhcHBlclByb3BzLFxuICBTdHlsZWRJbnB1dFByb3BzLFxuICBUZXh0LFxufSBmcm9tICdAY29kZWNhZGVteS9nYW11dCc7XG5pbXBvcnQge1xuICBjb25kaXRpb25hbFN0eWxlcyxcbiAgZm9ybUZpZWxkU3R5bGVzLFxufSBmcm9tICdAY29kZWNhZGVteS9nYW11dC9kaXN0L0Zvcm0vc3R5bGVzJztcbmltcG9ydCB7IHRoZW1lIH0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQtc3R5bGVzJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJztcbmltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VSZWYgfSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IFNsYXNoID0gc3R5bGVkLnNwYW5gXG4gIHdpZHRoOiAwO1xuICBmb250LWZhbWlseTogJ1N1aXNzZSc7XG4gIHRyYW5zZm9ybTogdHJhbnNsYXRlKC02cHgsIDFweCk7XG4gIGZvbnQtc2l6ZTogMThweDtcbmA7XG5cbmZ1bmN0aW9uIGZvY3VzQm9yZGVyQ29sb3IoeyB2YXJpYW50IH06IFN0eWxlZElucHV0UHJvcHMpIHtcbiAgcmV0dXJuIHZhcmlhbnQgPT09ICdlcnJvcidcbiAgICA/IHRoZW1lLmNvbG9yc1snZmVlZGJhY2stZXJyb3InXVxuICAgIDogdGhlbWUuY29sb3JzLnByaW1hcnk7XG59XG5cbmNvbnN0IElucHV0SW5uZXJCb3ggPSBzdHlsZWQuZGl2PFN0eWxlZElucHV0UHJvcHM+YFxuICAke2Zvcm1GaWVsZFN0eWxlc31cbiAgJHtjb25kaXRpb25hbFN0eWxlc31cbiAgJiA+IGRpdiB7XG4gICAgd2lkdGg6IDEwMCU7XG4gIH1cbiAgcGFkZGluZzogMDtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgaGVpZ2h0OiAzLjEyNXJlbTtcbiAgLnJlY3VybHktZWxlbWVudCB7XG4gICAgaGVpZ2h0OiAzLjEyNXJlbTtcbiAgfVxuICAmOmhhcygucmVjdXJseS1lbGVtZW50LWZvY3VzKSB7XG4gICAgYm9yZGVyLWNvbG9yOiAke2ZvY3VzQm9yZGVyQ29sb3J9O1xuICAgIGJveC1zaGFkb3c6IGluc2V0IDAgMCAwIDFweCAke2ZvY3VzQm9yZGVyQ29sb3J9O1xuICB9XG4gICY6aGFzKCR7U2xhc2h9KSA+IGRpdjpmaXJzdC1vZi10eXBlIHtcbiAgICBtYXgtd2lkdGg6IDIuNzVyZW07XG4gICAgbWluLXdpZHRoOiAyLjc1cmVtO1xuICB9XG5gO1xuXG5leHBvcnQgdHlwZSBSZWN1cmx5RmllbGRQcm9wcyA9IElucHV0V3JhcHBlclByb3BzICYgeyBsYWJlbDogc3RyaW5nIH07XG5cbi8qKlxuICogQSB3cmFwcGVyIGFyb3VuZCBhIFJlY3VybHkgZWxlbWVudCAob3IgdHdvIGVsZW1lbnRzIGluIHRoZSBjYXNlIG9mIE1NL1lZKSB0b1xuICogYWRkIEdhbXV0IGJvcmRlciBzdHlsaW5nIGFuZCBhIGxhYmVsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVjdXJseUZpZWxkKHsgbGFiZWwsIGNoaWxkcmVuLCAuLi5wcm9wcyB9OiBSZWN1cmx5RmllbGRQcm9wcykge1xuICBjb25zdCByZWYgPSB1c2VSZWY8SFRNTERpdkVsZW1lbnQ+KG51bGwpO1xuXG4gIGNvbnN0IHNlbGVjdElmcmFtZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZWYuY3VycmVudD8ucXVlcnlTZWxlY3RvcignaWZyYW1lJyk/LmZvY3VzKCk7XG4gIH0sIFtdKTtcblxuICByZXR1cm4gKFxuICAgIDxCb3ggcmVmPXtyZWZ9PlxuICAgICAgPFRleHQgYXM9XCJsYWJlbFwiIG9uQ2xpY2s9e3NlbGVjdElmcmFtZX0+XG4gICAgICAgIHtsYWJlbH1cbiAgICAgIDwvVGV4dD5cbiAgICAgIDxJbnB1dCBhcz17SW5wdXRJbm5lckJveH0gey4uLnByb3BzfT5cbiAgICAgICAge0FycmF5LmlzQXJyYXkoY2hpbGRyZW4pICYmIGNoaWxkcmVuLmxlbmd0aCA9PT0gMiA/IChcbiAgICAgICAgICA8PlxuICAgICAgICAgICAge2NoaWxkcmVuWzBdfVxuICAgICAgICAgICAgPFNsYXNoPi88L1NsYXNoPlxuICAgICAgICAgICAge2NoaWxkcmVuWzFdfVxuICAgICAgICAgIDwvPlxuICAgICAgICApIDogKFxuICAgICAgICAgIGNoaWxkcmVuXG4gICAgICAgICl9XG4gICAgICA8L0lucHV0PlxuICAgIDwvQm94PlxuICApO1xufVxuIl19 */",
17
- toString: _EMOTION_STRINGIFIED_CSS_ERROR__
18
- });
19
- function focusBorderColor({
20
- variant
21
- }) {
22
- return variant === 'error' ? theme.colors['feedback-error'] : theme.colors.primary;
23
- }
24
- const InputInnerBox = /*#__PURE__*/_styled("div", {
25
- target: "e1ndrvyp0",
26
- label: "InputInnerBox"
27
- })(formFieldStyles, " ", conditionalStyles, " &>div{width:100%;}padding:0;display:flex;align-items:center;height:3.125rem;.recurly-element{height:3.125rem;}&:has(.recurly-element-focus){border-color:", focusBorderColor, ";box-shadow:inset 0 0 0 1px ", focusBorderColor, ";}&:has(", Slash, ")>div:first-of-type{max-width:2.75rem;min-width:2.75rem;}" + (process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9SZWN1cmx5L2ZpZWxkcy9SZWN1cmx5RmllbGQudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTRCa0QiLCJmaWxlIjoiLi4vLi4vLi4vc3JjL1JlY3VybHkvZmllbGRzL1JlY3VybHlGaWVsZC50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBCb3gsXG4gIElucHV0LFxuICBJbnB1dFdyYXBwZXJQcm9wcyxcbiAgU3R5bGVkSW5wdXRQcm9wcyxcbiAgVGV4dCxcbn0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQnO1xuaW1wb3J0IHtcbiAgY29uZGl0aW9uYWxTdHlsZXMsXG4gIGZvcm1GaWVsZFN0eWxlcyxcbn0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQvZGlzdC9Gb3JtL3N0eWxlcyc7XG5pbXBvcnQgeyB0aGVtZSB9IGZyb20gJ0Bjb2RlY2FkZW15L2dhbXV0LXN0eWxlcyc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5pbXBvcnQgeyB1c2VDYWxsYmFjaywgdXNlUmVmIH0gZnJvbSAncmVhY3QnO1xuXG5jb25zdCBTbGFzaCA9IHN0eWxlZC5zcGFuYFxuICB3aWR0aDogMDtcbiAgZm9udC1mYW1pbHk6ICdTdWlzc2UnO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNnB4LCAxcHgpO1xuICBmb250LXNpemU6IDE4cHg7XG5gO1xuXG5mdW5jdGlvbiBmb2N1c0JvcmRlckNvbG9yKHsgdmFyaWFudCB9OiBTdHlsZWRJbnB1dFByb3BzKSB7XG4gIHJldHVybiB2YXJpYW50ID09PSAnZXJyb3InXG4gICAgPyB0aGVtZS5jb2xvcnNbJ2ZlZWRiYWNrLWVycm9yJ11cbiAgICA6IHRoZW1lLmNvbG9ycy5wcmltYXJ5O1xufVxuXG5jb25zdCBJbnB1dElubmVyQm94ID0gc3R5bGVkLmRpdjxTdHlsZWRJbnB1dFByb3BzPmBcbiAgJHtmb3JtRmllbGRTdHlsZXN9XG4gICR7Y29uZGl0aW9uYWxTdHlsZXN9XG4gICYgPiBkaXYge1xuICAgIHdpZHRoOiAxMDAlO1xuICB9XG4gIHBhZGRpbmc6IDA7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGhlaWdodDogMy4xMjVyZW07XG4gIC5yZWN1cmx5LWVsZW1lbnQge1xuICAgIGhlaWdodDogMy4xMjVyZW07XG4gIH1cbiAgJjpoYXMoLnJlY3VybHktZWxlbWVudC1mb2N1cykge1xuICAgIGJvcmRlci1jb2xvcjogJHtmb2N1c0JvcmRlckNvbG9yfTtcbiAgICBib3gtc2hhZG93OiBpbnNldCAwIDAgMCAxcHggJHtmb2N1c0JvcmRlckNvbG9yfTtcbiAgfVxuICAmOmhhcygke1NsYXNofSkgPiBkaXY6Zmlyc3Qtb2YtdHlwZSB7XG4gICAgbWF4LXdpZHRoOiAyLjc1cmVtO1xuICAgIG1pbi13aWR0aDogMi43NXJlbTtcbiAgfVxuYDtcblxuZXhwb3J0IHR5cGUgUmVjdXJseUZpZWxkUHJvcHMgPSBJbnB1dFdyYXBwZXJQcm9wcyAmIHsgbGFiZWw6IHN0cmluZyB9O1xuXG4vKipcbiAqIEEgd3JhcHBlciBhcm91bmQgYSBSZWN1cmx5IGVsZW1lbnQgKG9yIHR3byBlbGVtZW50cyBpbiB0aGUgY2FzZSBvZiBNTS9ZWSkgdG9cbiAqIGFkZCBHYW11dCBib3JkZXIgc3R5bGluZyBhbmQgYSBsYWJlbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlY3VybHlGaWVsZCh7IGxhYmVsLCBjaGlsZHJlbiwgLi4ucHJvcHMgfTogUmVjdXJseUZpZWxkUHJvcHMpIHtcbiAgY29uc3QgcmVmID0gdXNlUmVmPEhUTUxEaXZFbGVtZW50PihudWxsKTtcblxuICBjb25zdCBzZWxlY3RJZnJhbWUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgcmVmLmN1cnJlbnQ/LnF1ZXJ5U2VsZWN0b3IoJ2lmcmFtZScpPy5mb2N1cygpO1xuICB9LCBbXSk7XG5cbiAgcmV0dXJuIChcbiAgICA8Qm94IHJlZj17cmVmfT5cbiAgICAgIDxUZXh0IGFzPVwibGFiZWxcIiBvbkNsaWNrPXtzZWxlY3RJZnJhbWV9PlxuICAgICAgICB7bGFiZWx9XG4gICAgICA8L1RleHQ+XG4gICAgICA8SW5wdXQgYXM9e0lucHV0SW5uZXJCb3h9IHsuLi5wcm9wc30+XG4gICAgICAgIHtBcnJheS5pc0FycmF5KGNoaWxkcmVuKSAmJiBjaGlsZHJlbi5sZW5ndGggPT09IDIgPyAoXG4gICAgICAgICAgPD5cbiAgICAgICAgICAgIHtjaGlsZHJlblswXX1cbiAgICAgICAgICAgIDxTbGFzaD4vPC9TbGFzaD5cbiAgICAgICAgICAgIHtjaGlsZHJlblsxXX1cbiAgICAgICAgICA8Lz5cbiAgICAgICAgKSA6IChcbiAgICAgICAgICBjaGlsZHJlblxuICAgICAgICApfVxuICAgICAgPC9JbnB1dD5cbiAgICA8L0JveD5cbiAgKTtcbn1cbiJdfQ== */"));
28
- /**
29
- * A wrapper around a Recurly element (or two elements in the case of MM/YY) to
30
- * add Gamut border styling and a label.
31
- */
32
- export function RecurlyField({
33
- label,
34
- children,
35
- ...props
36
- }) {
37
- const ref = useRef(null);
38
- const selectIframe = useCallback(() => {
39
- ref.current?.querySelector('iframe')?.focus();
40
- }, []);
41
- return /*#__PURE__*/_jsxs(Box, {
42
- ref: ref,
43
- children: [/*#__PURE__*/_jsx(Text, {
44
- as: "label",
45
- onClick: selectIframe,
46
- children: label
47
- }), /*#__PURE__*/_jsx(Input, {
48
- as: InputInnerBox,
49
- ...props,
50
- children: Array.isArray(children) && children.length === 2 ? /*#__PURE__*/_jsxs(_Fragment, {
51
- children: [children[0], /*#__PURE__*/_jsx(Slash, {
52
- children: "/"
53
- }), children[1]]
54
- }) : children
55
- })]
56
- });
57
- }
@@ -1,17 +0,0 @@
1
- import type { Emitter } from '@recurly/recurly-js/lib/emitter';
2
- export declare const CardNumber: import("react").ForwardRefExoticComponent<EventHandlers & import("react").RefAttributes<Focusable>>;
3
- export declare const ExpMonth: import("react").ForwardRefExoticComponent<EventHandlers & import("react").RefAttributes<Focusable>>;
4
- export declare const ExpYear: import("react").ForwardRefExoticComponent<EventHandlers & import("react").RefAttributes<Focusable>>;
5
- export declare const CVV: import("react").ForwardRefExoticComponent<EventHandlers & import("react").RefAttributes<Focusable>>;
6
- export type ElementType = 'CardNumberElement' | 'CardMonthElement' | 'CardYearElement' | 'CardCvvElement';
7
- export type EventHandler = Parameters<Emitter['on']>[1];
8
- export type EventHandlers = {
9
- onReady?: EventHandler;
10
- onChange?: EventHandler;
11
- onBlur?: EventHandler;
12
- onFocus?: EventHandler;
13
- onSubmit?: EventHandler;
14
- };
15
- export type Focusable = {
16
- focus: () => void;
17
- };
@@ -1,106 +0,0 @@
1
- import { formFieldPaddingStyles } from '@codecademy/gamut/dist/Form/styles';
2
- import { forwardRef, useMemo, useRef } from 'react';
3
- import { useElements } from '../context';
4
- import { jsx as _jsx } from "react/jsx-runtime";
5
- export const CardNumber = element('CardNumberElement', 'Card number');
6
- export const ExpMonth = element('CardMonthElement', 'Expiration month', 'MM');
7
- export const ExpYear = element('CardYearElement', 'Expiration year', 'YY');
8
- export const CVV = element('CardCvvElement', 'CVV');
9
-
10
- /* These match methods on `ElementsInstance`. 'CardElement' is omitted since we
11
- only need individual elements (number,month,year,cvv). */
12
-
13
- // The type that `element.on` expects. See `bindEventHandlers`.
14
-
15
- /* Our only reason for allowing folks to pass in a ref is so that they can call
16
- `.focus()` from the outside. This type satisfies `HTMLElement` (the type one
17
- might try to use) and `ElementInstance` (what we actually set the ref to). */
18
-
19
- /**
20
- * Defines a Recurly element component for a given type.
21
- */
22
- function element(type, title, placeholder) {
23
- return /*#__PURE__*/forwardRef((eventHandlers, ref) => {
24
- const elements = useElements({
25
- noProviderError: 'Recurly element must be used within a Elements provider.'
26
- });
27
-
28
- // Keep ref updated with current event handlers. See `bindEventHandlers`.
29
- const h = useRef({});
30
- h.current = eventHandlers;
31
- const callback = useMemo(() => {
32
- if (!elements) return null;
33
- let el;
34
- return div => {
35
- /* This is called once (with the div) when `elements` is defined and
36
- once (with null) on component unmount. */
37
- if (div) {
38
- el = elements[type]({
39
- style: getStyle(title, placeholder)
40
- });
41
- el.attach(div);
42
- bindEventHandlers(el, h);
43
- allowFocus(div, ref, el);
44
- } else {
45
- cleanup(el);
46
- }
47
- };
48
- }, [elements, ref]);
49
- return /*#__PURE__*/_jsx("div", {
50
- ref: callback
51
- });
52
- });
53
- }
54
- function cleanup(el) {
55
- /* `.destroy()` is not documented or included in the IndividualElement type,
56
- but there is an example of @recurly/react-recurly using it here:
57
- https://github.com/recurly/react-recurly/blob/main/lib/element/element.jsx#L112 */
58
- el?.destroy();
59
- }
60
- function allowFocus(div, ref, el) {
61
- // Forward focus from iframe to element. (used by RecurlyField label onClick)
62
- div.querySelector('iframe')?.addEventListener('focus', () => el.focus());
63
-
64
- // Set ref to our Recurly element instance so that one can call `.focus()`.
65
- if (ref instanceof Function) {
66
- ref(el); // call RefCallback
67
- } else if (ref) {
68
- ref.current = el; // set RefObject
69
- }
70
- }
71
- function getStyle(title, placeholder) {
72
- const {
73
- px,
74
- py
75
- } = formFieldPaddingStyles;
76
- return {
77
- /* We can't use Apercu in the iframe, but Recurly will pull in any Google
78
- font. JetBrains Mono seems appropriate for card info. */
79
- fontFamily: 'JetBrains Mono',
80
- /* Most Gamut styling is applied outside the iframe by RecurlyField. We
81
- apply padding in the iframe to ensure the entire element is clickable. */
82
- padding: `${px}px ${py}px`,
83
- /* For some bewildered reason, Recurly takes `title` and `placeholder` as
84
- style properties. Title is necessary for screen readers. */
85
- title,
86
- /* The spread syntax for `placeholder` is only necessary because Recurly is
87
- persnickety about only including it when defined. */
88
- ...(placeholder ? {
89
- placeholder
90
- } : {})
91
- };
92
- }
93
-
94
- /* When event handlers are passed as inline function props, they technically are
95
- new function instances on each render. Rather than re-attaching the handlers on
96
- each render, we keep a ref updated with the latest handlers and bind static
97
- handlers that call the dynamic handlers from the ref. @recurly/react-recurly
98
- essentially uses the same approach here:
99
- https://github.com/recurly/react-recurly/blob/main/lib/element/element.jsx#L102 */
100
- function bindEventHandlers(el, h) {
101
- el.on('attach', (...args) => h.current?.onReady?.(...args));
102
- el.on('change', (...args) => h.current?.onChange?.(...args));
103
- el.on('blur', (...args) => h.current?.onBlur?.(...args));
104
- el.on('focus', (...args) => h.current?.onFocus?.(...args));
105
- el.on('submit', (...args) => h.current?.onSubmit?.(...args));
106
- }