gwchq-textjam 0.5.17 → 0.5.19

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.
package/README.md CHANGED
@@ -30,8 +30,7 @@ You will also see any lint errors in the console.
30
30
 
31
31
  ### `yarn test`
32
32
 
33
- Launches the test runner in interactive watch mode.\
34
- See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
33
+ Runs the Jest test suite once and exits. Pass `--watch` (e.g. `yarn test --watch`) for interactive watch mode, or `--coverage` to generate a coverage report.
35
34
 
36
35
  ### `yarn build:lib`
37
36
 
@@ -39,9 +38,7 @@ Builds the lib for production to the `dist` folder.\
39
38
  It bundles React in production mode and optimizes the build for the best performance.
40
39
 
41
40
  The build is minified and the filenames include the hashes.\
42
- Your app is ready to be deployed!
43
-
44
- See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
41
+ The library is ready to be published — see [Publishing to npm](#publishing-to-npm) below.
45
42
 
46
43
  ## Styling
47
44
 
@@ -87,7 +84,7 @@ export function ComponentName() {
87
84
 
88
85
  ## Testing
89
86
 
90
- Automated unit tests can be run via the `yarn test` command. These unit tests are written using the JavaScript testing framework `Jest` and make use of the tools provided by the [React Testing Library](https://testing-library.com/docs/). Automated accessibility testing for components is available via the `jest-axe` library. This can be achieved using the `haveNoViolations` matcher provided by `jest-axe`, although this does not guarantee that the tested components have no accessibility issues.
87
+ Automated unit tests can be run via the `yarn test` command. These unit tests are written using the JavaScript testing framework `Jest` and make use of the tools provided by the [React Testing Library](https://testing-library.com/docs/). Automated accessibility testing for components is available via the `jest-axe` library. This can be achieved using the `toHaveNoViolations` matcher provided by `jest-axe`, although this does not guarantee that the tested components have no accessibility issues.
91
88
 
92
89
  ## Publishing to npm
93
90
 
@@ -127,11 +124,12 @@ The following files are included in the npm package (as defined in `package.json
127
124
  Consumers can import:
128
125
 
129
126
  - Main component: `import { TextJamEditor } from "gwchq-textjam"`
127
+ - `CurriculumDisplayMode` enum and `useCurriculumDisplayMode` hook: `import { CurriculumDisplayMode, useCurriculumDisplayMode } from "gwchq-textjam"`
130
128
  - Stylesheet: `import "gwchq-textjam/style.css"`
131
129
 
132
130
  # Using the editor as a React component
133
131
 
134
- The editor can be imported and rendered directly inside another React application. The package exports the `TextJamEditor` component and `styles.css`:
132
+ The editor can be imported and rendered directly inside another React application:
135
133
 
136
134
  ```tsx
137
135
  import { TextJamEditor } from "gwchq-textjam";
@@ -140,7 +138,23 @@ import "gwchq-textjam/style.css";
140
138
  export function EditorWrapper() {
141
139
  return (
142
140
  <TextJamEditor
143
- project={{ project_type: "python", identifier: "my-py-app" }}
141
+ project={{
142
+ project_type: "python",
143
+ identifier: "my-py-app",
144
+ name: "My Python App",
145
+ rootDirId: "root",
146
+ components: [],
147
+ commits: [],
148
+ }}
149
+ isLoading={false}
150
+ user={{
151
+ userId: 1,
152
+ firstName: "Ada",
153
+ lastName: "Lovelace",
154
+ initials: "AL",
155
+ isFacilitator: false,
156
+ avatarSrc: "",
157
+ }}
144
158
  />
145
159
  );
146
160
  }
@@ -209,43 +223,42 @@ The consumer's webpack config should include the following setups
209
223
 
210
224
  ### Component props
211
225
 
212
- `TextJamEditor` accepts the following props (previously exposed as web-component attributes):
226
+ `TextJamEditor` accepts the following props (see `TextJamEditorProps` in `src/App.tsx` for the source of truth):
213
227
 
214
- - `project`: an object with the project data. Contains the following props:
215
- - `project_type`: Possible values `web` | `python`. Default project files will be created according to this value
216
- - `identifier`: A string that represents the project id. If provided, cached project with same id will be loaded
217
- - `author`: an object with owner user data (firstName, lastName, id)
218
- - `components`: an array of project components (files and folders)
219
- - `packageApiUrl`: A string with url to download pyodide packages. If not provided - default value is pyodide CDN.
220
- - `isSharedProject`: a boolean to show a shared project interface instead the regular editor if `true` (`false` by default)
221
- - `isCodeVisible`: a boolean to show or hide the code panel (`true` by default)
228
+ **Required**
229
+
230
+ - `project` (`IncomingProjectData`): the project data. Contains `project_type` (`"web"` | `"python"`), `identifier`, `name`, `rootDirId`, `components` (files and folders), `commits`, and optionally `author`, `commitId`, `savedAt`, `extension`, etc.
231
+ - `isLoading`: a boolean indicating whether the project is still loading.
232
+ - `user` (`AuthorizedUser`): the authenticated user — `userId`, `firstName`, `lastName`, `initials`, `isFacilitator`, `avatarSrc`.
222
233
 
223
- // TODO: review old options below
234
+ **Optional**
235
+
236
+ - `packageApiUrl`: A string with url to download pyodide packages. If not provided, the default value is the pyodide CDN.
237
+ - `isSharedProject`: a boolean to show a shared project interface instead of the regular editor if `true` (`false` by default)
238
+ - `isCodeVisible`: a boolean to show or hide the code panel (`true` by default)
239
+ - `template`: a `Project` used as the starter/template content.
240
+ - `curriculum`: a `Curriculum` object (`{ curriculumDisplayMode, curriculumContent }`) controlling the embedded curriculum panel. `curriculumDisplayMode` is one of `CurriculumDisplayMode.HIDDEN | NORMAL | EXPANDED`.
241
+ - `saveProject`: `(options: { project, commitBlob?, hasContentChanges?, hasNameChanges?, skipRedirect? }) => void | Promise<void>` — called by the editor when a save is triggered.
242
+ - `isSaving`: a boolean reflecting whether a save is in progress.
243
+ - `loadProjectContent`: a `LoadProjectContentFunction` used to fetch project content on demand.
244
+ - `projectContent`: pre-loaded project content (a zip `Blob`) to inflate instead of fetching it.
245
+ - `starterCodeContent`: a `Blob | null` with starter code content.
246
+ - `shareLinks`: `{ showCode, hideCode } | null` — links for sharing the project.
247
+ - `isContentLoaded` / `isSaveSuccess`: `boolean | null` flags surfaced by the host app's load/save flow.
248
+ - `loadTemplateProjectData`: callback to trigger loading of template project data.
249
+ - `isTemplateDataLoaded`: a boolean indicating whether template data has finished loading.
250
+ - `navigationGuardCoordinator`: a `NavigationGuardCoordinator` (`{ register(guard, shouldBlock?) }`) the host app can use to intercept navigation while there are unsaved changes.
251
+ - `onLogoutClick` / `onViewProfileClick` / `onHomeClick`: callbacks fired from the editor's auth/nav menu.
224
252
 
225
- - `loadCache`: Load latest version of project code from local storage (defaults to `true`)
226
- - `locale`: Locale for UI elements and to determine the language of projects loaded from the API (defaults to `en`)
227
- - `outputOnly`: Only display the output panel (defaults to `false`)
228
- - `outputPanels`: Array of output panel names to display (defaults to `['text', 'visual']`)
229
- - `outputSplitView`: Start with split view in output panel (defaults to `false`, i.e. tabbed view)
230
- - `projectNameEditable`: Allow the user to edit the project name in the project bar (defaults to `false`)
231
- - `readOnly`: Display the editor in read-only mode (defaults to `false`)
232
- - `sidebarOptions`: Array of strings specifying the panels to be displayed in the sidebar. Options include `"projects"`, `"file"`, `"download"`, `"settings"`.
253
+ `sidebarOptions` (`string[]`, defaults to `["files", "home", "user"]`) is also accepted at runtime and forwarded down to the sidebar
233
254
 
234
- When no props are supplied the component falls back to parsing the current page’s query string so the local development experience (`yarn start`) continues to work unchanged. You can override this by explicitly passing `queryString` or the equivalent props.
255
+ ### Client-side storage
235
256
 
236
- ### Events and callbacks
257
+ **IndexedDB** is the editor's actual project cache. It opens a `textjam-store` database (`src/utils/IndexedDb.ts`) with three object stores — `files` (file blobs), `projects` (project metadata, keyed by project key, stamped with `savedAt`), and `project_files` (the list of file ids belonging to a project). The `useProjectCache` hook reads/writes this cache so a project's latest content survives a reload without a round trip to the host app.
237
258
 
238
- For backwards compatibility the editor continues to dispatch the following `document` events. You can listen for them from your host application if you rely on the legacy integration layer:
259
+ **`localStorage`** is used only for a small cross-tab notification, not for storing project content:
239
260
 
240
- - `editor-codeChanged`
241
- - `editor-navigateToProjectsPage`
242
- - `editor-projectOwnerLoaded`
243
- - `editor-runCompleted`
244
- - `editor-runStarted`
245
- - `editor-stepChanged`
246
- - `editor-logIn`
247
- - `editor-signUp`
248
- - `editor-quizReady`
249
- - `editor-themeUpdated`
261
+ - `src/utils/projectTabSync.ts` writes a `project-updated` key (`{ key, timestamp, source }`) whenever the active project changes.
262
+ - Other open tabs pick this up via the `storage` event (`listenProjectUpdates`) and, through the `useProjectTabSync` hook, show a "made changes in another tab, refresh to see your updates" toast. Preview tabs and the tab that made the change are excluded.
250
263
 
251
- These events make it possible for the host page to react to code execution, project changes, authentication requests, and theme updates.
264
+ Inside the sandboxed iframe used to run HTML/JS projects, the editor also overrides `window.localStorage` (`src/components/Editor/Runners/HtmlRunner/helpers/scripts.ts`) to block reads/writes/removal of `authKey` and any `oidc.*` key, and disables `clear()` entirely — this prevents user-authored preview code from reading or tampering with the host app's auth tokens.
package/dist/index.js CHANGED
@@ -46543,7 +46543,7 @@ var Project = props => {
46543
46543
  (0,external_react_.useMemo)(() => {
46544
46544
  var isDesktop = params["width-larger-than-720"];
46545
46545
  setDefaultWidth(isDesktop ? "50%" : "100%");
46546
- setDefaultHeight(isDesktop ? "100%" : "50%");
46546
+ setDefaultHeight(isDesktop ? "100%" : "33.33%");
46547
46547
  setMaxWidth(isDesktop ? "75%" : "100%");
46548
46548
  setHandleDirection(isDesktop ? "right" : "bottom");
46549
46549
  }, [params["width-larger-than-720"]]);
@@ -82853,9 +82853,10 @@ const useFileTree = ({ projectFiles, onRename, onDrop, onOpenFile, rootId, readO
82853
82853
  tree.rebuildTree();
82854
82854
  }, [projectFiles, tree]);
82855
82855
  // A leftover dnd state disables every hotkey; `dragend` never comes when the
82856
- // dragged row unmounts. Capture + microtask: their handler runs between them.
82856
+ // dragged row unmounts. Capture + task, not microtask: a native dispatch runs
82857
+ // microtasks between listeners, i.e. before their drop handler reads it.
82857
82858
  (0, react_2.useEffect)(() => {
82858
- const clearDndState = () => queueMicrotask(() => tree.applySubStateUpdate("dnd", null));
82859
+ const clearDndState = () => setTimeout(() => tree.applySubStateUpdate("dnd", null));
82859
82860
  document.addEventListener("drop", clearDndState, true);
82860
82861
  return () => document.removeEventListener("drop", clearDndState, true);
82861
82862
  }, [tree]);
package/dist/style.css CHANGED
@@ -703,10 +703,10 @@
703
703
  .styles-module__previewContainer--gHB-N{block-size:100%;display:flex;align-items:center;justify-content:center}
704
704
  :root{--rpf-white: #ffffff}.styles-module__tabContainer--4HWO\+{display:flex;align-items:stretch}.styles-module__scrollWrapper--xi36s{position:relative;flex:1;min-inline-size:0;overflow-x:auto;overflow-y:hidden;white-space:nowrap;scrollbar-color:HSL(0, 0%, 14%, 30%) rgba(0,0,0,0);scrollbar-width:none;-ms-overflow-style:none}.styles-module__scrollWrapper--xi36s::-webkit-scrollbar{block-size:0;transition:height .2s ease}.styles-module__scrollWrapper--xi36s:hover{scrollbar-width:thin}.styles-module__scrollWrapper--xi36s:hover::-webkit-scrollbar{block-size:calc(.25rem*var(--scale-factor, 1))}.styles-module__tabScrollButton--uVTTR{flex:0 0 32px;inline-size:32px;min-inline-size:32px;block-size:100%;padding:0;border:0;border-radius:0;background-color:#e5f6f1;display:flex;align-items:center;justify-content:center}.styles-module__tabScrollButton--uVTTR:hover,.styles-module__tabScrollButton--uVTTR:focus,.styles-module__tabScrollButton--uVTTR:active,.styles-module__tabScrollButton--uVTTR:disabled{background-color:#e5f6f1}.styles-module__tabScrollButton--uVTTR:disabled svg path{stroke:#cbcbcb}.styles-module__tabScrollButtonLeft--qLxhp{border-inline-end:1px solid #e5e5e5;border-start-start-radius:calc(.5rem*var(--scale-factor, 1))}.styles-module__tabScrollButtonLeft--qLxhp svg{transform:rotate(180deg)}.styles-module__tabScrollButtonRight--VbQha{border-inline-start:1px solid #e5e5e5;border-start-end-radius:calc(.5rem*var(--scale-factor, 1))}.styles-module__hasNavigationControls--3adJi .draggable-tab:last-child,.styles-module__hasNavigationControls--3adJi .react-tabs__tab:last-child{border-inline-end:0}.styles-module__overlayContent--7CQ\+-{position:absolute;inset-block:0;inset-inline-start:0;z-index:1;display:flex;align-items:center}
705
705
  :root{--rpf-white: #ffffff}.styles-module__readOnlyContainer--GooG6{display:flex;justify-content:flex-end;margin:8px 4px 4px 4px}.styles-module__readOnlyContainerLeft--D6yHv{justify-content:flex-start}.styles-module__readOnlyBanner--b4PPC{background-color:#e5e5e5;padding:4px 8px;border-radius:12px;font-weight:400;font-size:calc(.5rem*var(--scale-factor, 1));line-height:calc(1rem*var(--scale-factor, 1));display:flex;gap:4px;align-items:center;color:#69746d}
706
- :root{--rpf-white: #ffffff}.styles-module__proj--ZFm0o{display:flex;flex-flow:column;overflow:hidden;block-size:100%}.styles-module__projContainer--foKo4{display:flex;flex-direction:row;overflow:clip;overflow-clip-margin:1.25rem;margin:0 8px 6px 0px;block-size:100%;min-block-size:0}.styles-module__projContainer--foKo4 .styles-module__projectWrapper--Yq8Yr{container-type:inline-size;display:flex;flex-direction:column;flex:1 1 auto;overflow:clip;overflow-clip-margin:1.25rem;min-block-size:0;min-inline-size:0}.styles-module__projContainer--foKo4 .styles-module__projEditorWrapper--SISJR{display:flex;flex:0 1 auto;flex-flow:column;grid-gap:calc(.625rem*var(--scale-factor, 1));overflow:clip;overflow-clip-margin:1.25rem;block-size:100%;inline-size:100%;min-block-size:0;min-inline-size:0}@container (min-width: 720px){.styles-module__projContainer--foKo4 .styles-module__projEditorWrapper--SISJR{flex-flow:row}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR{max-block-size:100% !important}}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR{display:flex;box-sizing:border-box;background-color:#fff;min-block-size:30%;max-block-size:70%;border-radius:8px;box-shadow:0px 4px 20px 0px rgba(0,0,0,.15)}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-panel--selected--RwR-m{overflow-y:hidden}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-list--gM7uT{flex:1}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-container--ycENl .styles-module__btn--run--u9TgZ,.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-container--ycENl .styles-module__btn--stop--gJCsY{margin-block-start:0;margin-block-end:0}
706
+ :root{--rpf-white: #ffffff}.styles-module__proj--ZFm0o{display:flex;flex-flow:column;overflow:hidden;block-size:100%}.styles-module__projContainer--foKo4{display:flex;flex-direction:row;overflow:clip;overflow-clip-margin:1.25rem;margin:0 8px 6px 0px;block-size:100%;min-block-size:0}.styles-module__projContainer--foKo4 .styles-module__projectWrapper--Yq8Yr{container-type:inline-size;display:flex;flex-direction:column;flex:1 1 auto;overflow:clip;overflow-clip-margin:1.25rem;min-block-size:0;min-inline-size:0}.styles-module__projContainer--foKo4 .styles-module__projEditorWrapper--SISJR{display:flex;flex:0 1 auto;flex-flow:column;grid-gap:calc(.625rem*var(--scale-factor, 1));overflow:clip;overflow-clip-margin:1.25rem;block-size:100%;inline-size:100%;min-block-size:0;min-inline-size:0}@container (min-width: 720px){.styles-module__projContainer--foKo4 .styles-module__projEditorWrapper--SISJR{flex-flow:row}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR{max-block-size:100% !important}}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR{display:flex;box-sizing:border-box;background-color:#fff;min-block-size:30%;max-block-size:70%;border-radius:8px;box-shadow:0px 4px 20px 0px rgba(0,0,0,.15)}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .resizable-with-handle__handle--bottom>div{inset-block-end:calc(-1*calc(0.625rem * var(--scale-factor, 1))) !important}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-panel--selected--RwR-m{overflow-y:hidden}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-list--gM7uT{flex:1}.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-container--ycENl .styles-module__btn--run--u9TgZ,.styles-module__projContainer--foKo4 .styles-module__projEditorContainer--jWAlR .styles-module__react-tabs__tab-container--ycENl .styles-module__btn--stop--gJCsY{margin-block-start:0;margin-block-end:0}
707
707
  :root{--rpf-white: #ffffff}.styles-module__viewSwitcher--h0ODR{display:flex}.styles-module__viewSwitcherBtn--v6-ir{inline-size:calc(2.75rem*var(--scale-factor, 1));block-size:calc(2.75rem*var(--scale-factor, 1));cursor:pointer;transition:background-color .15s ease}.styles-module__viewSwitcherBtnWrapper--OarYg{position:relative;display:flex}.styles-module__viewSwitcherBtnWrapper--OarYg:first-child .styles-module__viewSwitcherBtn--v6-ir{border-radius:calc(.75rem*var(--scale-factor, 1)) 0 0 calc(.75rem*var(--scale-factor, 1))}.styles-module__viewSwitcherBtnWrapper--OarYg:last-child .styles-module__viewSwitcherBtn--v6-ir{border-radius:0 calc(.75rem*var(--scale-factor, 1)) calc(.75rem*var(--scale-factor, 1)) 0}.styles-module__viewSwitcherBtnActive--m2JP-{background-color:#fff}
708
708
  :root{--rpf-white: #ffffff}.styles-module__container--uYbdi{color:#e0201c;padding:calc(.75rem*var(--scale-factor, 1)) calc(1.25rem*var(--scale-factor, 1));display:flex;flex-direction:column;gap:calc(1rem*var(--scale-factor, 1));flex:0 0 auto}.styles-module__message--hNGZt{padding:0;margin:0;white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:18px;font-family:"Roboto Mono",source-code-pro,Menlo,Monaco,Consolas,"Courier New",monospace}.styles-module__infoBox--Ti35B{inline-size:100%;overflow-wrap:break-word;padding:calc(.5rem*var(--scale-factor, 1));background-color:#ffd5ce;color:#520e0e;display:flex;flex-direction:row;align-items:start;justify-content:flex-start;border:1px solid #e0201c;border-radius:calc(.5rem*var(--scale-factor, 1));gap:calc(.25rem*var(--scale-factor, 1))}.styles-module__infoBox--Ti35B svg{color:#e0201c}.styles-module__infoText--jXz2P{display:flex;flex-direction:column;align-items:flex-start;gap:calc(.3125rem*var(--scale-factor, 1))}.styles-module__notFoundContainer--YfNdr{inline-size:100%;block-size:100%;display:flex;flex-direction:column;align-items:center;gap:calc(2rem*var(--scale-factor, 1));padding:calc(2rem*var(--scale-factor, 1)) calc(1rem*var(--scale-factor, 1));overflow:scroll;justify-content:space-evenly}.styles-module__notFoundText--q6EKC{display:flex;flex-direction:column;align-items:center;gap:calc(1rem*var(--scale-factor, 1))}
709
- :root{--rpf-white: #ffffff}.styles-module__pythonrunnerContainer---nPGz,.styles-module__outputStackContainer--7Y14r{display:flex;flex-direction:column;flex:1;gap:calc(.625rem*var(--scale-factor, 1));block-size:100%;inline-size:100%}.styles-module__resizeHandleContainer--FID6p{inline-size:100%;margin-block-start:calc(-1*calc(1.5rem * var(--scale-factor, 1)))}.styles-module__console--B8x1A{padding:calc(.75rem*var(--scale-factor, 1)) calc(1rem*var(--scale-factor, 1));margin:0;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;inline-size:100%;word-wrap:break-word;overflow-y:auto;color:#242424;font-size:13px;line-height:18px;font-family:"Roboto Mono",source-code-pro,Menlo,Monaco,Consolas,"Courier New",monospace;scrollbar-width:thin}.styles-module__consoleMount--1BJWe{display:contents}.styles-module__pythonGraphic--V\+du6{overflow:auto;position:relative}.styles-module__pyodiderunner--DKTtB{display:none}.styles-module__pyodiderunner--DKTtB.styles-module__active--bKVnT{display:flex}.styles-module__visualOutput--WLaca{flex:1;display:flex;min-block-size:100%;inline-size:100%}.styles-module__outputPanel--W1TnW{block-size:100%;display:flex;overflow:hidden;background-color:#fff;border-radius:calc(.5rem*var(--scale-factor, 1));box-shadow:0px 4px 20px 0px rgba(0,0,0,.15);flex:5}.styles-module__pythonConsoleLine--bwFQC{padding-inline-end:5px}.styles-module__pythonConsoleLine--bwFQC.styles-module__stderr--PIyhL{color:red}.styles-module__pythonrunnerInput--dOXEa{caret-color:inherit;color:#2467ec;display:block;line-height:20px;padding:2px 1px 2px 0}.styles-module__pythonrunnerInput--dOXEa:focus{outline:0}.styles-module__webConsole--MTdnk{padding:calc(.25rem*var(--scale-factor, 1));scrollbar-width:thin;font-size:12px}.styles-module__consoleMessageInline--5pNbC{display:inline-flex;align-items:center;gap:calc(.5rem*var(--scale-factor, 1));vertical-align:top}.styles-module__consoleMessageInline--5pNbC>span{align-self:flex-start}.styles-module__webConsoleLine--j31U1{display:flex;align-items:flex-start;flex-wrap:wrap;padding:0 calc(.25rem*var(--scale-factor, 1)) 0 calc(1.5rem*var(--scale-factor, 1));margin-block-end:calc(.25rem*var(--scale-factor, 1));border-block-end:1px solid #e5e5e5}.styles-module__webConsoleLine--j31U1:last-child{border-block-end:0}.styles-module__webConsoleLine--j31U1>span:first-child{display:flex;align-items:center;flex-shrink:0;white-space:nowrap}.styles-module__webConsoleLine--j31U1>span:last-child{flex:1;word-break:break-word}.styles-module__webConsoleLine--j31U1>span:last-child:has(>details){flex:1 1 100%}.styles-module__consoleMessageContent--vXp1a{flex:1;min-inline-size:0;word-break:break-word}.styles-module__consoleGroupInline--eMSGy{gap:calc(.25rem*var(--scale-factor, 1));cursor:pointer}.styles-module__consoleGroupInline--eMSGy:has(.styles-module__groupToggle--wji1w:focus-visible){outline:2px solid #242424;outline-offset:1px;border-radius:calc(.25rem*var(--scale-factor, 1))}.styles-module__consoleCount--JLMn5{flex:0 0 auto;display:inline-flex;align-items:center;block-size:14px;padding:0 calc(.25rem*var(--scale-factor, 1));border-radius:calc(.5rem*var(--scale-factor, 1));background:#e5e5e5;color:#33353d;line-height:14px;white-space:nowrap;font-size:calc(.75rem*var(--scale-factor, 1));line-height:calc(1rem*var(--scale-factor, 1))}.styles-module__string--YDxWc{color:#242424}.styles-module__stringInsideStructure--KJtZp{color:#a31746}.styles-module__number--7h5TG,.styles-module__boolean--WYb4I{color:#0169e1}.styles-module__null--BZCmR,.styles-module__undefined--nQkol{color:#242424}.styles-module__key--ZZTlD{color:#cb69cd;flex-shrink:0;white-space:nowrap}.styles-module__error--RL5Lt{border-radius:calc(.25rem*var(--scale-factor, 1));padding-inline-start:calc(.5rem*var(--scale-factor, 1));background:#ffd5ce}.styles-module__errorIcon--Gnn4-{margin-inline-end:calc(.25rem*var(--scale-factor, 1));color:#e0201c}.styles-module__warn--B\+MPR{border-radius:calc(.25rem*var(--scale-factor, 1));padding-inline-start:calc(.5rem*var(--scale-factor, 1));background:#fffbe3}.styles-module__warnIcon--Q82Y5{margin-inline-end:calc(.25rem*var(--scale-factor, 1));color:#a88f00}.styles-module__timestamp--HDZxD{color:#69746d;margin-inline-end:calc(.625rem*var(--scale-factor, 1))}.styles-module__details--W1bGT{display:inline-block}.styles-module__summary--vms5d{display:inline-flex;align-items:center;gap:calc(.25rem*var(--scale-factor, 1));cursor:pointer}.styles-module__summary--vms5d::-webkit-details-marker{display:none}.styles-module__summary--vms5d::marker{content:""}.styles-module__nestedEntry--OU25X{display:flex;gap:calc(.25rem*var(--scale-factor, 1));padding-inline-start:calc(1rem*var(--scale-factor, 1))}.styles-module__previewLink--rWLII{margin-inline-start:auto;padding-block-start:calc(.25rem*var(--scale-factor, 1));border:none;background:none;cursor:pointer;display:inline-flex;padding-inline:0}.styles-module__visualPanePadding--ytRHn{padding:calc(.25rem*var(--scale-factor, 1))}.styles-module__iframe--YfQ0V{border:none;border-radius:calc(.25rem*var(--scale-factor, 1));background-color:#fff;block-size:100%;inline-size:100%;pointer-events:auto}.styles-module__iframe--YfQ0V.styles-module__codeHasBeenRun--fqiYL{border:1px solid #e5e5e5}.styles-module__iframe--YfQ0V.styles-module__focused--a\+AT8{outline:2px auto Highlight;outline:2px auto -webkit-focus-ring-color;outline-offset:-1px}.styles-module__groupToggle--wji1w{display:inline-flex;align-self:flex-start;border:0;padding:0;background:rgba(0,0,0,0);color:inherit;font:inherit;line-height:inherit;cursor:pointer;transform:translateY(3px)}.styles-module__groupToggle--wji1w:focus-visible{border:0;outline:none}.styles-module__disclosureIcon--YhmPO{display:block;color:#242424;transform-origin:center}.styles-module__details--W1bGT[open]>.styles-module__summary--vms5d .styles-module__disclosureIcon--YhmPO{transform:rotate(90deg)}.styles-module__disclosureIconExpanded--7vJIm{transform:rotate(90deg)}.styles-module__domTag--S1Ue1,.styles-module__domChild--ZN87f,.styles-module__domClosingTag--8IMaS{line-height:16px}.styles-module__domTag--S1Ue1{white-space:nowrap}.styles-module__domTagName--AA4s5{color:#269b90}.styles-module__domAttributeValue--qHrw\+{color:#a31746}.styles-module__domChildren--eouIw,.styles-module__domClosingTag--8IMaS{padding-inline-start:calc(1rem*var(--scale-factor, 1))}.styles-module__webConsoleLine--j31U1.styles-module__consoleTableLine--CPbzK{padding-inline:0;border-block-end:0}.styles-module__webConsoleLine--j31U1.styles-module__consoleTableLine--CPbzK>span:first-child{flex:1 1 100%;padding-inline:calc(1.5rem*var(--scale-factor, 1)) calc(.25rem*var(--scale-factor, 1))}.styles-module__webConsoleLine--j31U1.styles-module__consoleTableLine--CPbzK>span:last-child{flex:1 1 100%}.styles-module__consoleTableLabel--gjNJE{color:#966efc}.styles-module__consoleTable--nptEa{inline-size:100%;border-collapse:collapse;table-layout:fixed}.styles-module__consoleTable--nptEa th,.styles-module__consoleTable--nptEa td{padding:0;border:1px solid #e5e5e5;font-weight:inherit;text-align:center;vertical-align:middle}.styles-module__previewSlot--V8txy{block-size:100%;inline-size:100%}.styles-module__previewHost--20-DL{position:absolute;z-index:50;overflow:hidden;border-radius:calc(.25rem*var(--scale-factor, 1));pointer-events:none;display:none}#p5Sketch{display:flex;flex:1;position:absolute}.pythonrunner-graphic{overflow:auto;position:relative}
709
+ :root{--rpf-white: #ffffff}.styles-module__pythonrunnerContainer---nPGz,.styles-module__outputStackContainer--7Y14r{display:flex;flex-direction:column;flex:1;gap:calc(.625rem*var(--scale-factor, 1));block-size:100%;inline-size:100%;min-block-size:0}.styles-module__resizeHandleContainer--FID6p{inline-size:100%;margin-block-start:calc(-1*calc(1.5rem * var(--scale-factor, 1)))}.styles-module__console--B8x1A{padding:calc(.75rem*var(--scale-factor, 1)) calc(1rem*var(--scale-factor, 1));margin:0;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;inline-size:100%;word-wrap:break-word;overflow-y:auto;color:#242424;font-size:13px;line-height:18px;font-family:"Roboto Mono",source-code-pro,Menlo,Monaco,Consolas,"Courier New",monospace;scrollbar-width:thin}.styles-module__consoleMount--1BJWe{display:contents}.styles-module__pythonGraphic--V\+du6{overflow:auto;position:relative}.styles-module__pyodiderunner--DKTtB{display:none}.styles-module__pyodiderunner--DKTtB.styles-module__active--bKVnT{display:flex}.styles-module__visualOutput--WLaca{flex:1;display:flex;min-block-size:100%;inline-size:100%}.styles-module__outputPanel--W1TnW{block-size:100%;display:flex;overflow:hidden;background-color:#fff;border-radius:calc(.5rem*var(--scale-factor, 1));box-shadow:0px 4px 20px 0px rgba(0,0,0,.15);flex:5}.styles-module__pythonConsoleLine--bwFQC{padding-inline-end:5px}.styles-module__pythonConsoleLine--bwFQC.styles-module__stderr--PIyhL{color:red}.styles-module__pythonrunnerInput--dOXEa{caret-color:inherit;color:#2467ec;display:block;line-height:20px;padding:2px 1px 2px 0}.styles-module__pythonrunnerInput--dOXEa:focus{outline:0}.styles-module__webConsole--MTdnk{padding:calc(.25rem*var(--scale-factor, 1));scrollbar-width:thin;font-size:12px}.styles-module__consoleMessageInline--5pNbC{display:inline-flex;align-items:center;gap:calc(.5rem*var(--scale-factor, 1));vertical-align:top}.styles-module__consoleMessageInline--5pNbC>span{align-self:flex-start}.styles-module__webConsoleLine--j31U1{display:flex;align-items:flex-start;flex-wrap:wrap;padding:0 calc(.25rem*var(--scale-factor, 1)) 0 calc(1.5rem*var(--scale-factor, 1));margin-block-end:calc(.25rem*var(--scale-factor, 1));border-block-end:1px solid #e5e5e5}.styles-module__webConsoleLine--j31U1:last-child{border-block-end:0}.styles-module__webConsoleLine--j31U1>span:first-child{display:flex;align-items:center;flex-shrink:0;white-space:nowrap}.styles-module__webConsoleLine--j31U1>span:last-child{flex:1;word-break:break-word}.styles-module__webConsoleLine--j31U1>span:last-child:has(>details){flex:1 1 100%}.styles-module__consoleMessageContent--vXp1a{flex:1;min-inline-size:0;word-break:break-word}.styles-module__consoleGroupInline--eMSGy{gap:calc(.25rem*var(--scale-factor, 1));cursor:pointer}.styles-module__consoleGroupInline--eMSGy:has(.styles-module__groupToggle--wji1w:focus-visible){outline:2px solid #242424;outline-offset:1px;border-radius:calc(.25rem*var(--scale-factor, 1))}.styles-module__consoleCount--JLMn5{flex:0 0 auto;display:inline-flex;align-items:center;block-size:14px;padding:0 calc(.25rem*var(--scale-factor, 1));border-radius:calc(.5rem*var(--scale-factor, 1));background:#e5e5e5;color:#33353d;line-height:14px;white-space:nowrap;font-size:calc(.75rem*var(--scale-factor, 1));line-height:calc(1rem*var(--scale-factor, 1))}.styles-module__string--YDxWc{color:#242424}.styles-module__stringInsideStructure--KJtZp{color:#a31746}.styles-module__number--7h5TG,.styles-module__boolean--WYb4I{color:#0169e1}.styles-module__null--BZCmR,.styles-module__undefined--nQkol{color:#242424}.styles-module__key--ZZTlD{color:#cb69cd;flex-shrink:0;white-space:nowrap}.styles-module__error--RL5Lt{border-radius:calc(.25rem*var(--scale-factor, 1));padding-inline-start:calc(.5rem*var(--scale-factor, 1));background:#ffd5ce}.styles-module__errorIcon--Gnn4-{margin-inline-end:calc(.25rem*var(--scale-factor, 1));color:#e0201c}.styles-module__warn--B\+MPR{border-radius:calc(.25rem*var(--scale-factor, 1));padding-inline-start:calc(.5rem*var(--scale-factor, 1));background:#fffbe3}.styles-module__warnIcon--Q82Y5{margin-inline-end:calc(.25rem*var(--scale-factor, 1));color:#a88f00}.styles-module__timestamp--HDZxD{color:#69746d;margin-inline-end:calc(.625rem*var(--scale-factor, 1))}.styles-module__details--W1bGT{display:inline-block}.styles-module__summary--vms5d{display:inline-flex;align-items:center;gap:calc(.25rem*var(--scale-factor, 1));cursor:pointer}.styles-module__summary--vms5d::-webkit-details-marker{display:none}.styles-module__summary--vms5d::marker{content:""}.styles-module__nestedEntry--OU25X{display:flex;gap:calc(.25rem*var(--scale-factor, 1));padding-inline-start:calc(1rem*var(--scale-factor, 1))}.styles-module__previewLink--rWLII{margin-inline-start:auto;padding-block-start:calc(.25rem*var(--scale-factor, 1));border:none;background:none;cursor:pointer;display:inline-flex;padding-inline:0}.styles-module__visualPanePadding--ytRHn{padding:calc(.25rem*var(--scale-factor, 1))}.styles-module__iframe--YfQ0V{border:none;border-radius:calc(.25rem*var(--scale-factor, 1));background-color:#fff;block-size:100%;inline-size:100%;pointer-events:auto}.styles-module__iframe--YfQ0V.styles-module__codeHasBeenRun--fqiYL{border:1px solid #e5e5e5}.styles-module__iframe--YfQ0V.styles-module__focused--a\+AT8{outline:2px auto Highlight;outline:2px auto -webkit-focus-ring-color;outline-offset:-1px}.styles-module__groupToggle--wji1w{display:inline-flex;align-self:flex-start;border:0;padding:0;background:rgba(0,0,0,0);color:inherit;font:inherit;line-height:inherit;cursor:pointer;transform:translateY(3px)}.styles-module__groupToggle--wji1w:focus-visible{border:0;outline:none}.styles-module__disclosureIcon--YhmPO{display:block;color:#242424;transform-origin:center}.styles-module__details--W1bGT[open]>.styles-module__summary--vms5d .styles-module__disclosureIcon--YhmPO{transform:rotate(90deg)}.styles-module__disclosureIconExpanded--7vJIm{transform:rotate(90deg)}.styles-module__domTag--S1Ue1,.styles-module__domChild--ZN87f,.styles-module__domClosingTag--8IMaS{line-height:16px}.styles-module__domTag--S1Ue1{white-space:nowrap}.styles-module__domTagName--AA4s5{color:#269b90}.styles-module__domAttributeValue--qHrw\+{color:#a31746}.styles-module__domChildren--eouIw,.styles-module__domClosingTag--8IMaS{padding-inline-start:calc(1rem*var(--scale-factor, 1))}.styles-module__webConsoleLine--j31U1.styles-module__consoleTableLine--CPbzK{padding-inline:0;border-block-end:0}.styles-module__webConsoleLine--j31U1.styles-module__consoleTableLine--CPbzK>span:first-child{flex:1 1 100%;padding-inline:calc(1.5rem*var(--scale-factor, 1)) calc(.25rem*var(--scale-factor, 1))}.styles-module__webConsoleLine--j31U1.styles-module__consoleTableLine--CPbzK>span:last-child{flex:1 1 100%}.styles-module__consoleTableLabel--gjNJE{color:#966efc}.styles-module__consoleTable--nptEa{inline-size:100%;border-collapse:collapse;table-layout:fixed}.styles-module__consoleTable--nptEa th,.styles-module__consoleTable--nptEa td{padding:0;border:1px solid #e5e5e5;font-weight:inherit;text-align:center;vertical-align:middle}.styles-module__previewSlot--V8txy{block-size:100%;inline-size:100%}.styles-module__previewHost--20-DL{position:absolute;z-index:50;overflow:hidden;border-radius:calc(.25rem*var(--scale-factor, 1));pointer-events:none;display:none}#p5Sketch{display:flex;flex:1;position:absolute}.pythonrunner-graphic{overflow:auto;position:relative}
710
710
  :root{--rpf-white: #ffffff}.styles-module__container--cs4\+2{align-self:center;justify-self:center;inline-size:100%;text-align:center;color:#69746d}.styles-module__container--cs4\+2 span{display:block}.styles-module__title--7NEra{color:#003046}
711
711
  :root{--rpf-white: #ffffff}.styles-module__projRunnerContainer--ImBw-{display:flex;flex:5;border-radius:calc(.5rem*var(--scale-factor, 1));overflow:visible}.styles-module__projRunnerContainer--ImBw- .styles-module__react-tabs__tab-panel--selected--z2CLa{overflow-y:auto}.styles-module__projRunnerContainer--ImBw- .styles-module__react-tabs__tab-list--GLkmj{flex:1}.styles-module__projRunnerContainer--ImBw- .styles-module__react-tabs__tab-container--yOCPX .styles-module__btn--run--Nwouj,.styles-module__projRunnerContainer--ImBw- .styles-module__react-tabs__tab-container--yOCPX .styles-module__btn--stop--NAmPu{margin-block-start:0;margin-block-end:0}
712
712
  :root{--rpf-white: #ffffff}.styles-module__outputPreview--dHe0z{display:flex;flex:1 1 auto;block-size:auto;overflow:hidden;background-color:#fff}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gwchq-textjam",
3
3
  "description": "Embeddable React editor used in Raspberry Pi text-based projects.",
4
- "version": "0.5.17",
4
+ "version": "0.5.19",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/GirlsFirst/gwchq-textjam",
7
7
  "author": "Girls Who Code HQ",