@codecademy/codebytes 0.6.0 → 0.6.2-alpha.0cf60d.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 (61) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/MonacoEditor/colorsDark.d.ts +32 -0
  3. package/{src/MonacoEditor/colorsDark.ts → dist/MonacoEditor/colorsDark.js} +8 -16
  4. package/dist/MonacoEditor/index.d.ts +7 -0
  5. package/dist/MonacoEditor/index.js +42 -0
  6. package/dist/MonacoEditor/theme.d.ts +2 -0
  7. package/dist/MonacoEditor/theme.js +122 -0
  8. package/dist/MonacoEditor/types.d.ts +1 -0
  9. package/dist/MonacoEditor/types.js +0 -0
  10. package/dist/__tests__/codebyte-test.d.ts +1 -0
  11. package/dist/__tests__/codebyte-test.js +195 -0
  12. package/dist/__tests__/editor-test.d.ts +1 -0
  13. package/dist/__tests__/editor-test.js +147 -0
  14. package/dist/__tests__/helpers-test.d.ts +1 -0
  15. package/dist/__tests__/helpers-test.js +117 -0
  16. package/dist/__tests__/language-selection-test.d.ts +1 -0
  17. package/dist/__tests__/language-selection-test.js +15 -0
  18. package/dist/__tests__/mocks.d.ts +0 -0
  19. package/dist/__tests__/mocks.js +13 -0
  20. package/dist/api.d.ts +12 -0
  21. package/dist/api.js +39 -0
  22. package/dist/codeByteEditor.d.ts +13 -0
  23. package/dist/codeByteEditor.js +133 -0
  24. package/dist/consts.d.ts +23 -0
  25. package/dist/consts.js +34 -0
  26. package/dist/drawers.d.ts +6 -0
  27. package/dist/drawers.js +148 -0
  28. package/dist/editor.d.ts +13 -0
  29. package/dist/editor.js +189 -0
  30. package/dist/helpers/index.d.ts +15 -0
  31. package/dist/helpers/index.js +29 -0
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.js +2 -0
  34. package/dist/languageSelection.d.ts +6 -0
  35. package/dist/languageSelection.js +22 -0
  36. package/dist/libs/eventTracking.d.ts +1 -0
  37. package/dist/libs/eventTracking.js +11 -0
  38. package/{src → dist}/theme.d.ts +0 -0
  39. package/dist/types.d.ts +14 -0
  40. package/dist/types.js +0 -0
  41. package/package.json +7 -3
  42. package/babel.config.js +0 -15
  43. package/jest.config.js +0 -1
  44. package/src/MonacoEditor/index.tsx +0 -56
  45. package/src/MonacoEditor/theme.ts +0 -64
  46. package/src/MonacoEditor/types.ts +0 -1
  47. package/src/__tests__/codebyte-test.tsx +0 -197
  48. package/src/__tests__/editor-test.tsx +0 -113
  49. package/src/__tests__/helpers-test.tsx +0 -121
  50. package/src/__tests__/language-selection-test.tsx +0 -14
  51. package/src/__tests__/mocks.ts +0 -8
  52. package/src/api.ts +0 -28
  53. package/src/consts.ts +0 -64
  54. package/src/drawers.tsx +0 -132
  55. package/src/editor.tsx +0 -160
  56. package/src/helpers/index.ts +0 -41
  57. package/src/index.tsx +0 -118
  58. package/src/languageSelection.tsx +0 -26
  59. package/src/libs/eventTracking.ts +0 -18
  60. package/src/types.ts +0 -15
  61. package/tsconfig.json +0 -8
package/src/editor.tsx DELETED
@@ -1,160 +0,0 @@
1
- import {
2
- FillButton,
3
- FlexBox,
4
- Spinner,
5
- TextButton,
6
- ToolTip,
7
- } from '@codecademy/gamut';
8
- import { CopyIcon } from '@codecademy/gamut-icons';
9
- import styled from '@emotion/styled';
10
- import React, { useState } from 'react';
11
-
12
- import { postSnippet } from './api';
13
- import type { LanguageOption } from './consts';
14
- import { Drawers } from './drawers';
15
- import { trackClick } from './helpers';
16
- import { SimpleMonacoEditor } from './MonacoEditor';
17
- import { CodebytesChangeHandler } from './types';
18
-
19
- const Output = styled.pre<{ hasError: boolean }>`
20
- width: 100%;
21
- height: 100%;
22
- margin: 0;
23
- padding: 0 1rem;
24
- font-family: Monaco;
25
- font-size: 0.875rem;
26
- overflow: auto;
27
- ${({ hasError, theme }) => `
28
- color: ${hasError ? theme.colors.orange : theme.colors.white};
29
- background-color: ${theme.colors['navy-900']};
30
- `}
31
- `;
32
-
33
- const CopyIconStyled = styled(CopyIcon)`
34
- margin-right: 0.5rem;
35
- `;
36
-
37
- const DOCKER_SIGTERM = 143;
38
-
39
- type EditorProps = {
40
- hideCopyButton: boolean;
41
- language: LanguageOption;
42
- text: string;
43
- onChange: (text: string) => void;
44
- snippetsBaseUrl?: string;
45
- onCopy?: CodebytesChangeHandler;
46
- };
47
-
48
- export const Editor: React.FC<EditorProps> = ({
49
- language,
50
- text,
51
- hideCopyButton,
52
- onChange,
53
- onCopy,
54
- snippetsBaseUrl,
55
- }) => {
56
- const [output, setOutput] = useState('');
57
- const [status, setStatus] = useState<'ready' | 'waiting' | 'error'>('ready');
58
- const [isCodeByteCopied, setIsCodeByteCopied] = useState(false);
59
- const onCopyClick = () => {
60
- if (!isCodeByteCopied) {
61
- navigator.clipboard
62
- .writeText(text)
63
- // eslint-disable-next-line no-console
64
- .catch(() => console.error('Failed to copy'));
65
- setIsCodeByteCopied(true);
66
- onCopy?.(text, language);
67
- trackClick('copy');
68
- }
69
- };
70
-
71
- const setErrorStatusAndOutput = (message: string) => {
72
- setOutput(message);
73
- setStatus('error');
74
- };
75
-
76
- const handleSubmit = async () => {
77
- if (text.trim().length === 0) {
78
- return;
79
- }
80
- const data = {
81
- language,
82
- code: text,
83
- };
84
- setStatus('waiting');
85
- setOutput('');
86
- trackClick('run');
87
-
88
- try {
89
- const response = await postSnippet(data, snippetsBaseUrl);
90
- if (response.stderr.length > 0) {
91
- setErrorStatusAndOutput(response.stderr);
92
- } else if (response.exit_code === DOCKER_SIGTERM) {
93
- setErrorStatusAndOutput(
94
- 'Your code took too long to return a result. Double check your code for any issues and try again!'
95
- );
96
- } else if (response.exit_code !== 0) {
97
- setErrorStatusAndOutput('An unknown error occured.');
98
- } else {
99
- setOutput(response.stdout);
100
- setStatus('ready');
101
- }
102
- } catch (error) {
103
- setErrorStatusAndOutput('Error: ' + error);
104
- }
105
- };
106
-
107
- return (
108
- <>
109
- <Drawers
110
- leftChild={
111
- <SimpleMonacoEditor
112
- value={text}
113
- language={language}
114
- onChange={onChange}
115
- />
116
- }
117
- rightChild={
118
- <Output hasError={status === 'error'} aria-live="polite">
119
- {output}
120
- </Output>
121
- }
122
- />
123
- <FlexBox
124
- justifyContent={hideCopyButton ? 'flex-end' : 'space-between'}
125
- pl={8}
126
- >
127
- {!hideCopyButton ? (
128
- <ToolTip
129
- id="codebyte-copied"
130
- alignment="top-right"
131
- mode="dark"
132
- target={
133
- <TextButton
134
- variant="secondary"
135
- onClick={onCopyClick}
136
- onBlur={() => setIsCodeByteCopied(false)}
137
- data-testid="copy-codebyte-btn"
138
- >
139
- <CopyIconStyled aria-hidden="true" /> Copy Codebyte
140
- </TextButton>
141
- }
142
- >
143
- {isCodeByteCopied ? (
144
- <span data-testid="copy-confirmation-tooltip" role="alert">
145
- Copied!
146
- </span>
147
- ) : (
148
- <span data-testid="copy-prompt-tooltip">
149
- Copy to your clipboard
150
- </span>
151
- )}
152
- </ToolTip>
153
- ) : null}
154
- <FillButton onClick={handleSubmit}>
155
- {status === 'waiting' ? <Spinner /> : 'Run'}
156
- </FillButton>
157
- </FlexBox>
158
- </>
159
- );
160
- };
@@ -1,41 +0,0 @@
1
- import { trackUserClick } from '../libs/eventTracking';
2
-
3
- export type CodebyteOptions = {
4
- clientName: string;
5
- parentPage: string;
6
- renderMode: string;
7
- };
8
-
9
- export enum CodebytesParams {
10
- Language = 'lang',
11
- Text = 'text',
12
- CopyMode = 'copy-mode',
13
- ClientName = 'client-name',
14
- Page = 'page',
15
- Mode = 'mode',
16
- }
17
-
18
- export const getOptions = (): CodebyteOptions => {
19
- const currentUri = new URL(window.location.href);
20
-
21
- return {
22
- clientName:
23
- currentUri.searchParams.get(CodebytesParams.ClientName) || 'Unknown',
24
- parentPage:
25
- currentUri.searchParams.get(CodebytesParams.Page) || document.referrer,
26
- renderMode: currentUri.searchParams.get(CodebytesParams.Mode) || '',
27
- };
28
- };
29
-
30
- export const trackClick = (target: string) => {
31
- const options = getOptions();
32
- const page_name = options.renderMode
33
- ? `${options.clientName}_${options.renderMode}`
34
- : options.clientName;
35
-
36
- trackUserClick({
37
- page_name,
38
- context: options.parentPage,
39
- target,
40
- });
41
- };
package/src/index.tsx DELETED
@@ -1,118 +0,0 @@
1
- import { Box, IconButton } from '@codecademy/gamut';
2
- import { FaviconIcon } from '@codecademy/gamut-icons';
3
- import { Background, states, system } from '@codecademy/gamut-styles';
4
- import { StyleProps } from '@codecademy/variance';
5
- import styled from '@emotion/styled';
6
- import React, { useEffect, useState } from 'react';
7
-
8
- import { helloWorld, LanguageOption } from './consts';
9
- import { Editor } from './editor';
10
- import { getOptions, trackClick } from './helpers';
11
- import { LanguageSelection } from './languageSelection';
12
- import { trackUserImpression } from './libs/eventTracking';
13
- import { CodeByteEditorProps } from './types';
14
-
15
- const editorStates = states({
16
- isIFrame: { height: '100vh' },
17
- });
18
-
19
- const editorBaseStyles = system.css({
20
- border: 1,
21
- borderColor: 'gray-900',
22
- display: 'flex',
23
- flexDirection: 'column',
24
- height: '25rem',
25
- width: '43rem',
26
- overflow: 'hidden',
27
- });
28
- export interface EditorStyleProps
29
- extends StyleProps<typeof editorBaseStyles>,
30
- StyleProps<typeof editorStates> {}
31
-
32
- const EditorContainer = styled(Background)<EditorStyleProps>(
33
- editorBaseStyles,
34
- editorStates
35
- );
36
-
37
- export const CodeByteEditor: React.FC<CodeByteEditorProps> = ({
38
- text: initialText,
39
- language: initialLanguage,
40
- hideCopyButton = false,
41
- isIFrame = false,
42
- snippetsBaseUrl,
43
- onEdit,
44
- onLanguageChange,
45
- onCopy,
46
- }) => {
47
- const getInitialText = () => {
48
- if (initialText !== undefined) return initialText;
49
- return initialLanguage ? helloWorld[initialLanguage] : '';
50
- };
51
-
52
- const [text, setText] = useState<string>(getInitialText());
53
- const [language, setLanguage] = useState<LanguageOption>(
54
- initialLanguage ?? ''
55
- );
56
- const [hasBeenEdited, setHasBeenEdited] = useState(false);
57
-
58
- useEffect(() => {
59
- const options = getOptions();
60
- const page_name = options.renderMode
61
- ? `${options.clientName}_${options.renderMode}`
62
- : options.clientName;
63
-
64
- trackUserImpression({
65
- page_name,
66
- context: options.parentPage,
67
- target: 'codebyte',
68
- });
69
- }, []);
70
-
71
- return (
72
- <EditorContainer bg="black" as="main" isIFrame={isIFrame}>
73
- <Box borderBottom={1} borderColor="gray-900" py={4} pl={8}>
74
- <IconButton
75
- icon={FaviconIcon}
76
- variant="secondary"
77
- href="https://www.codecademy.com/"
78
- target="_blank"
79
- rel="noreferrer"
80
- aria-label="visit codecademy.com"
81
- onClick={() => trackClick('logo')}
82
- />
83
- </Box>
84
- {language ? (
85
- <Editor
86
- language={language}
87
- text={text}
88
- hideCopyButton={hideCopyButton}
89
- onChange={(newText: string) => {
90
- setText(newText);
91
- onEdit?.(newText, language);
92
- const { renderMode } = getOptions();
93
- if (!renderMode && hasBeenEdited === false) {
94
- setHasBeenEdited(true);
95
- trackClick('edit');
96
- }
97
- }}
98
- snippetsBaseUrl={snippetsBaseUrl}
99
- onCopy={onCopy}
100
- />
101
- ) : (
102
- <LanguageSelection
103
- onChange={(newLanguage) => {
104
- const newText: string =
105
- text || (newLanguage ? helloWorld[newLanguage] : '');
106
- setLanguage(newLanguage);
107
- setText(newText);
108
- trackClick('lang_select');
109
- onLanguageChange?.(newText, newLanguage);
110
- trackClick('lang_select');
111
- }}
112
- />
113
- )}
114
- </EditorContainer>
115
- );
116
- };
117
-
118
- export default CodeByteEditor;
@@ -1,26 +0,0 @@
1
- import { Select, Text } from '@codecademy/gamut';
2
- import { ColorMode } from '@codecademy/gamut-styles';
3
- import React from 'react';
4
-
5
- import type { LanguageOption } from './consts';
6
- import { LanguageOptions } from './consts';
7
-
8
- export type LanguageSelectionProps = {
9
- onChange: (newLanguage: LanguageOption) => void;
10
- };
11
-
12
- export const LanguageSelection: React.FC<LanguageSelectionProps> = ({
13
- onChange,
14
- }) => {
15
- return (
16
- <ColorMode mode="dark" flex={1} px={16} pt={48}>
17
- <Text mb={16}>Which language do you want to code in?</Text>
18
- <Select
19
- id="language-select"
20
- aria-label="Select a language"
21
- options={LanguageOptions}
22
- onChange={(e) => onChange(e.target.value as LanguageOption)}
23
- />
24
- </ColorMode>
25
- );
26
- };
@@ -1,18 +0,0 @@
1
- import { createTracker } from '@codecademy/tracking';
2
-
3
- const IS_DEV = process.env.NODE_ENV === 'development';
4
-
5
- // TODO: confirm tracking details and implementation DISC-447
6
- const tracker = createTracker({
7
- apiBaseUrl:
8
- typeof window === undefined
9
- ? 'https://www.codecademy.com'
10
- : window.location.origin,
11
- verbose: IS_DEV,
12
- });
13
-
14
- export const {
15
- click: trackUserClick,
16
- visit: trackUserVisit,
17
- impression: trackUserImpression,
18
- } = tracker;
package/src/types.ts DELETED
@@ -1,15 +0,0 @@
1
- import { LanguageOption } from './consts';
2
-
3
- export interface CodebytesChangeHandler {
4
- (text: string, language: LanguageOption): void;
5
- }
6
- export interface CodeByteEditorProps {
7
- text?: string;
8
- language?: LanguageOption;
9
- hideCopyButton?: boolean;
10
- onCopy?: CodebytesChangeHandler;
11
- isIFrame?: boolean;
12
- snippetsBaseUrl?: string;
13
- onEdit?: CodebytesChangeHandler;
14
- onLanguageChange?: CodebytesChangeHandler;
15
- }
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "include": ["../../typings/*.d.ts", "./src/**/*.ts", "./src/**/*.tsx"],
4
- "compilerOptions": {
5
- "allowJs": true,
6
- "outDir": "./dist"
7
- }
8
- }