sliftutils 0.6.6 → 0.7.1

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 (62) hide show
  1. package/builders/electronBuild.ts +101 -0
  2. package/builders/electronBuildRun.js +4 -0
  3. package/builders/extensionBuild.ts +15 -9
  4. package/builders/generateIndexDts.js +46 -0
  5. package/builders/hotReload.ts +96 -0
  6. package/builders/nodeJSBuild.ts +1 -1
  7. package/builders/setup.ts +182 -0
  8. package/builders/setupRun.js +4 -0
  9. package/builders/watch.ts +182 -0
  10. package/builders/watchRun.js +4 -0
  11. package/builders/webBuild.ts +2 -2
  12. package/builders/webRun.js +4 -0
  13. package/bundler/bundleEntry.ts +17 -9
  14. package/bundler/bundleEntryCaller.ts +1 -1
  15. package/bundler/bundleRequire.ts +21 -3
  16. package/electron/electronIndex.html +12 -0
  17. package/electron/electronMain.ts +29 -0
  18. package/electron/electronRenderer.tsx +33 -0
  19. package/extension/extBackground.ts +22 -0
  20. package/extension/extContentScript.ts +19 -0
  21. package/extension/manifest.json +29 -0
  22. package/index.d.ts +332 -0
  23. package/misc/environment.ts +28 -0
  24. package/nodejs/server.ts +16 -0
  25. package/package.json +28 -3
  26. package/render-utils/DropdownCustom.d.ts +23 -0
  27. package/render-utils/FullscreenModal.d.ts +12 -0
  28. package/render-utils/Input.d.ts +39 -0
  29. package/render-utils/InputLabel.d.ts +35 -0
  30. package/render-utils/InputPicker.d.ts +35 -0
  31. package/render-utils/LocalStorageParam.d.ts +12 -0
  32. package/render-utils/SyncedController.d.ts +38 -0
  33. package/render-utils/SyncedLoadingIndicator.d.ts +8 -0
  34. package/render-utils/Table.d.ts +32 -0
  35. package/render-utils/URLParam.d.ts +13 -0
  36. package/render-utils/asyncObservable.d.ts +3 -0
  37. package/render-utils/index.html +12 -0
  38. package/render-utils/mobxTyped.d.ts +1 -0
  39. package/render-utils/modal.d.ts +6 -0
  40. package/render-utils/observer.d.ts +17 -0
  41. package/spec.txt +5 -64
  42. package/storage/FileFolderAPI.tsx +1 -1
  43. package/storage/PendingManager.tsx +1 -1
  44. package/tsconfig.declarations.json +18 -0
  45. package/web/browser.tsx +37 -0
  46. package/web/index.html +32 -0
  47. /package/{web → render-utils}/DropdownCustom.tsx +0 -0
  48. /package/{web → render-utils}/FullscreenModal.tsx +0 -0
  49. /package/{web → render-utils}/GenericFormat.tsx +0 -0
  50. /package/{web → render-utils}/Input.tsx +0 -0
  51. /package/{web → render-utils}/InputLabel.tsx +0 -0
  52. /package/{web → render-utils}/InputPicker.tsx +0 -0
  53. /package/{web → render-utils}/LocalStorageParam.ts +0 -0
  54. /package/{web → render-utils}/SyncedController.ts +0 -0
  55. /package/{web → render-utils}/SyncedLoadingIndicator.tsx +0 -0
  56. /package/{web → render-utils}/Table.tsx +0 -0
  57. /package/{web → render-utils}/URLParam.ts +0 -0
  58. /package/{web → render-utils}/asyncObservable.ts +0 -0
  59. /package/{web → render-utils}/colors.tsx +0 -0
  60. /package/{web → render-utils}/mobxTyped.ts +0 -0
  61. /package/{web → render-utils}/modal.tsx +0 -0
  62. /package/{web → render-utils}/observer.tsx +0 -0
package/package.json CHANGED
@@ -1,17 +1,39 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "0.6.6",
3
+ "version": "0.7.1",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "scripts": {
7
7
  "type": "yarn tsc --noEmit",
8
- "build-nodejs": "yarn typenode ./builders/nodeJSBuild.ts",
8
+ "emit-dts": "yarn tsc --project tsconfig.declarations.json",
9
+ "generate-index-dts": "node ./builders/generateIndexDts.js",
10
+ "run-nodejs": "node ./build-nodejs/server.js",
11
+ "run-nodejs-dev": "typenode ./nodejs/server.ts",
12
+ "run-web": "node ./builders/webRun.js",
13
+ "run-electron": "node ./node_modules/electron/cli.js ./build-electron/electronMain.js",
14
+ "build-nodejs": "node ./builders/nodeJSBuildRun.js",
15
+ "build-web": "node ./builders/webBuildRun.js",
16
+ "build-extension": "node ./builders/extensionBuildRun.js",
17
+ "build-electron": "node ./builders/electronBuildRun.js",
18
+ "watch-nodejs": "node ./builders/watchRun.js --port 9876 \"nodejs/*.ts\" \"nodejs/*.tsx\" \"yarn build-nodejs\"",
19
+ "watch-web": "node ./builders/watchRun.js --port 9877 \"web/*.ts\" \"web/*.tsx\" \"yarn build-web\"",
20
+ "watch-extension": "node ./builders/watchRun.js --port 9878 \"extension/*.ts\" \"extension/*.tsx\" \"yarn build-extension\"",
21
+ "watch-electron": "node ./builders/watchRun.js --port 9879 \"electron/*.ts\" \"electron/*.tsx\" \"yarn build-electron\"",
9
22
  "notes": "mobx, preact, socket-function, typenode SHOULD be peerDependencies. But we want to use yarn (better dependency deduplication), so we can't use peerDependencies (as they aren't installed by default, which makes them a nightmare to use). If you want to override the versions, feel free to use overrides/resolutions."
10
23
  },
11
24
  "bin": {
12
25
  "build-nodejs": "./builders/nodeJSBuildRun.js",
26
+ "buildnodejs": "./builders/nodeJSBuildRun.js",
13
27
  "build-extension": "./builders/extensionBuildRun.js",
14
- "build-web": "./builders/webBuildRun.js"
28
+ "buildextension": "./builders/extensionBuildRun.js",
29
+ "build-web": "./builders/webBuildRun.js",
30
+ "buildweb": "./builders/webBuildRun.js",
31
+ "build-electron": "./builders/electronBuildRun.js",
32
+ "buildelectron": "./builders/electronBuildRun.js",
33
+ "slift-watch": "./builders/watchRun.js",
34
+ "sliftwatch": "./builders/watchRun.js",
35
+ "slift-setup": "./builders/setupRun.js",
36
+ "sliftsetup": "./builders/setupRun.js"
15
37
  },
16
38
  "dependencies": {
17
39
  "@types/shell-quote": "^1.7.5",
@@ -22,12 +44,15 @@
22
44
  "socket-function": "^0.155.0",
23
45
  "typenode": "^6.0.0",
24
46
  "typesafecss": "^0.26.0",
47
+ "ws": "^8.18.3",
25
48
  "yargs": "15.4.1"
26
49
  },
27
50
  "devDependencies": {
28
51
  "@types/chrome": "^0.0.237",
29
52
  "@types/yargs": "15.0.19",
30
53
  "debugbreak": "^0.9.9",
54
+ "electron": "^33.2.1",
55
+ "open": "^8.4.0",
31
56
  "typedev": "^0.1.1"
32
57
  }
33
58
  }
@@ -0,0 +1,23 @@
1
+ import preact from "preact";
2
+ import { LengthOrPercentage } from "typesafecss/cssTypes";
3
+ export declare class DropdownCustom<T> extends preact.Component<{
4
+ class?: string;
5
+ optionClass?: string;
6
+ title?: string;
7
+ value: T;
8
+ onChange: (value: T, index: number) => void;
9
+ maxWidth?: LengthOrPercentage;
10
+ options: {
11
+ value: T;
12
+ label: (isOpen: boolean) => preact.ComponentChild;
13
+ }[];
14
+ }> {
15
+ synced: {
16
+ isOpen: boolean;
17
+ tempIndexSelected: number | null;
18
+ };
19
+ onUnmount: (() => void)[];
20
+ componentDidMount(): void;
21
+ componentDidUnmount(): void;
22
+ render(): preact.JSX.Element;
23
+ }
@@ -0,0 +1,12 @@
1
+ import preact from "preact";
2
+ export declare function showFullscreenModal(contents: preact.ComponentChildren): void;
3
+ export declare class FullscreenModal extends preact.Component<{
4
+ parentState?: {
5
+ open: boolean;
6
+ };
7
+ onCancel?: () => void;
8
+ style?: preact.JSX.CSSProperties;
9
+ outerStyle?: preact.JSX.CSSProperties;
10
+ }> {
11
+ render(): preact.JSX.Element;
12
+ }
@@ -0,0 +1,39 @@
1
+ import preact from "preact";
2
+ export type InputProps = (preact.JSX.HTMLAttributes<HTMLInputElement> & {
3
+ /** ONLY throttles onChangeValue */
4
+ throttle?: number;
5
+ flavor?: "large" | "small" | "none";
6
+ focusOnMount?: boolean;
7
+ textarea?: boolean;
8
+ /** Update on key stroke, not on blur (just does onInput = onChange, as onInput already does this) */
9
+ hot?: boolean;
10
+ /** Updates arrow keys with modifier behavior to use larger numbers, instead of decimals. */
11
+ integer?: boolean;
12
+ /** Only works with number/integer */
13
+ reverseArrowKeyDirection?: boolean;
14
+ inputRef?: (x: HTMLInputElement | null) => void;
15
+ /** Don't blur on enter key */
16
+ noEnterKeyBlur?: boolean;
17
+ noFocusSelect?: boolean;
18
+ inputKey?: string;
19
+ fillWidth?: boolean;
20
+ autocompleteValues?: string[];
21
+ /** Forces the input to update when focused. Usually we hold updates, to prevent the user's
22
+ * typing to be interrupted by background updates.
23
+ * NOTE: "hot" is usually required when using this.
24
+ */
25
+ forceInputValueUpdatesWhenFocused?: boolean;
26
+ onChangeValue?: (value: string) => void;
27
+ });
28
+ export declare class Input extends preact.Component<InputProps> {
29
+ onFocusText: string;
30
+ firstFocus: boolean;
31
+ elem: HTMLInputElement | null;
32
+ lastValue: unknown;
33
+ lastChecked: unknown;
34
+ onChangeThrottle: undefined | {
35
+ throttle: number;
36
+ run: (newValue: string) => void;
37
+ };
38
+ render(): preact.JSX.Element;
39
+ }
@@ -0,0 +1,35 @@
1
+ import preact from "preact";
2
+ import { InputProps } from "./Input";
3
+ import { URLParamStr } from "./URLParam";
4
+ export type InputLabelProps = Omit<InputProps, "label" | "title"> & {
5
+ label?: preact.ComponentChild;
6
+ number?: boolean;
7
+ /** A number, AND, an integer. Changes behavior arrow arrow keys as well */
8
+ integer?: boolean;
9
+ checkbox?: boolean;
10
+ edit?: boolean;
11
+ alwaysShowPencil?: boolean;
12
+ outerClass?: string;
13
+ maxDecimals?: number;
14
+ percent?: boolean;
15
+ editClass?: string;
16
+ fontSize?: number;
17
+ tooltip?: string;
18
+ fillWidth?: boolean;
19
+ useDateUI?: boolean;
20
+ };
21
+ export declare const startGuessDateRange: number;
22
+ export declare const endGuessDateRange: number;
23
+ export declare class InputLabel extends preact.Component<InputLabelProps> {
24
+ synced: {
25
+ editting: boolean;
26
+ editInputValue: string;
27
+ editUpdateSeqNum: number;
28
+ };
29
+ render(): preact.JSX.Element;
30
+ }
31
+ export declare class InputLabelURL extends preact.Component<InputLabelProps & {
32
+ persisted: URLParamStr;
33
+ }> {
34
+ render(): preact.JSX.Element;
35
+ }
@@ -0,0 +1,35 @@
1
+ import preact from "preact";
2
+ export type InputOption<T> = {
3
+ value: T;
4
+ label?: preact.ComponentChild;
5
+ matchText?: string;
6
+ };
7
+ export type FullInputOption<T> = {
8
+ value: T;
9
+ label: preact.ComponentChild;
10
+ matchText: string;
11
+ };
12
+ export declare class InputPickerURL extends preact.Component<{
13
+ label?: preact.ComponentChild;
14
+ options: (string | InputOption<string>)[];
15
+ allowNonOptions?: boolean;
16
+ value: {
17
+ value: string;
18
+ };
19
+ }> {
20
+ render(): preact.JSX.Element;
21
+ }
22
+ export declare class InputPicker<T> extends preact.Component<{
23
+ label?: preact.ComponentChild;
24
+ picked: T[];
25
+ options: InputOption<T>[];
26
+ addPicked: (value: T) => void;
27
+ removePicked: (value: T) => void;
28
+ allowNonOptions?: boolean;
29
+ }> {
30
+ synced: {
31
+ pendingText: string;
32
+ focused: boolean;
33
+ };
34
+ render(): preact.JSX.Element;
35
+ }
@@ -0,0 +1,12 @@
1
+ export declare class LocalStorageParamStr {
2
+ readonly storageKey: string;
3
+ private defaultValue;
4
+ private state;
5
+ lastSetValue: string;
6
+ constructor(storageKey: string, defaultValue?: string);
7
+ forceUpdate(): void;
8
+ get(): string;
9
+ set(value: string): void;
10
+ get value(): string;
11
+ set value(value: string);
12
+ }
@@ -0,0 +1,38 @@
1
+ import { SocketRegistered } from "socket-function/SocketFunctionTypes";
2
+ type RemapFunction<T> = T extends (...args: infer Args) => Promise<infer Return> ? {
3
+ (...args: Args): Return | undefined;
4
+ promise(...args: Args): Promise<Return>;
5
+ refresh(...args: Args): void;
6
+ refreshAll(): void;
7
+ reset(...args: Args): void;
8
+ resetAll(): void;
9
+ isLoading(...args: Args): boolean;
10
+ setCache(cache: {
11
+ args: Args;
12
+ result: Return;
13
+ }): void;
14
+ } : T;
15
+ export declare function getSyncedController<T extends SocketRegistered>(controller: T, config?: {
16
+ /** When a controller call for a write finishes, we refresh all readers.
17
+ * - Invalidation is global, across all controllers.
18
+ */
19
+ reads?: {
20
+ [key in keyof T["nodes"][""]]?: string[];
21
+ };
22
+ writes?: {
23
+ [key in keyof T["nodes"][""]]?: string[];
24
+ };
25
+ }): {
26
+ (nodeId: string): {
27
+ [fnc in keyof T["nodes"][""]]: RemapFunction<T["nodes"][""][fnc]>;
28
+ } & {
29
+ resetAll(): void;
30
+ refreshAll(): void;
31
+ anyPending(): boolean;
32
+ };
33
+ resetAll(): void;
34
+ refreshAll(): void;
35
+ anyPending(): boolean;
36
+ rerenderAll(): void;
37
+ };
38
+ export {};
@@ -0,0 +1,8 @@
1
+ import * as preact from "preact";
2
+ export declare class SyncedLoadingIndicator extends preact.Component<{
3
+ controller: {
4
+ anyPending: () => boolean;
5
+ };
6
+ }> {
7
+ render(): preact.JSX.Element | null;
8
+ }
@@ -0,0 +1,32 @@
1
+ import preact from "preact";
2
+ import { JSXFormatter } from "./GenericFormat";
3
+ export type ColumnType<T = unknown, Row extends RowType = RowType> = undefined | null | {
4
+ center?: boolean;
5
+ title?: preact.ComponentChild;
6
+ formatter?: JSXFormatter<T, Row>;
7
+ };
8
+ export type RowType = {
9
+ [columnName: string]: unknown;
10
+ };
11
+ export type ColumnsType = {
12
+ [columnName: string]: ColumnType;
13
+ };
14
+ export type TableType<RowT extends RowType = RowType> = {
15
+ columns: {
16
+ [columnName in keyof RowT]?: ColumnType<RowT[columnName], RowT>;
17
+ };
18
+ rows: RowT[];
19
+ };
20
+ export declare class Table<RowT extends RowType> extends preact.Component<TableType<RowT> & {
21
+ class?: string;
22
+ cellClass?: string;
23
+ initialLimit?: number;
24
+ lineLimit?: number;
25
+ characterLimit?: number;
26
+ excludeEmptyColumns?: boolean;
27
+ }> {
28
+ state: {
29
+ limit: number;
30
+ };
31
+ render(): preact.JSX.Element;
32
+ }
@@ -0,0 +1,13 @@
1
+ export declare class URLParamStr {
2
+ readonly urlKey: string;
3
+ private state;
4
+ lastSetValue: string;
5
+ constructor(urlKey: string);
6
+ forceUpdate(): void;
7
+ get(): string;
8
+ set(value: string): void;
9
+ get value(): string;
10
+ set value(value: string);
11
+ }
12
+ export declare function batchUrlUpdate<T>(code: () => T): T;
13
+ export declare function createLink(params: [URLParamStr, string][]): string;
@@ -0,0 +1,3 @@
1
+ export declare function asyncCache<Args, T>(getValue: (args: Args) => Promise<T>): {
2
+ (args: Args): T | undefined;
3
+ };
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Web App</title>
6
+ </head>
7
+ <body>
8
+ <div id="app"></div>
9
+ <script src="./browser.js"></script>
10
+ </body>
11
+ </html>
12
+
@@ -0,0 +1 @@
1
+ export declare function configureMobxNextFrameScheduler(): void;
@@ -0,0 +1,6 @@
1
+ import preact from "preact";
2
+ export declare function showModal(config: {
3
+ contents: preact.ComponentChildren;
4
+ }): {
5
+ close: () => void;
6
+ };
@@ -0,0 +1,17 @@
1
+ import * as preact from "preact";
2
+ import { Reaction } from "mobx";
3
+ export declare function observer<T extends {
4
+ new (...args: any[]): {
5
+ render(): preact.ComponentChild;
6
+ forceUpdate(callback?: () => void): void;
7
+ componentWillUnmount?(): void;
8
+ };
9
+ }>(Constructor: T): {
10
+ new (...args: any[]): {
11
+ reaction: Reaction;
12
+ componentWillUnmount(): void;
13
+ render(...args: any[]): preact.ComponentChild;
14
+ forceUpdate(callback?: () => void): void;
15
+ };
16
+ readonly name: string;
17
+ } & T;
package/spec.txt CHANGED
@@ -1,66 +1,7 @@
1
- TODO:
2
-
3
-
4
- 4) New project with:
5
-
6
- We need bins and entry points for the common types of builds
7
- site
8
- build site, copy it
9
- electron
10
- build main process, copy it
11
- build render process, copy it
12
- copy the json config file?
1
+ Okay Omit our typings, and then I guess we have to merge them all into one file. Although, if they reference each other, that's going to be difficult.
13
2
 
14
- build-web
15
- - I guess it's the same as the Node.js build.
16
- - index.html file, which is optional.
17
- - Assets folder, which is optional.
18
- build-electron
3
+ Fix our typings.
4
+ ALSO, go fix our typings in socket-function as well
19
5
 
20
- watch helper script in bin
21
- - And have it automatically ignore .gitignored files
22
- - And have it also watch .watchignore
23
- - accepts port argument to broadcast when the build changes
24
-
25
- watcher port, and helper function for hot reloading (watchHotReload)
26
- - accepts port argument
27
- - if in the browser, refreshes
28
- - warns if it can't connect to the socket, specifying the watch script that should be used
29
- - in nodejs, instead use socket-function hot reloading
30
- - import { onHotReload, watchFilesAndTriggerHotReloading } from "socket-function/hot/HotReloadController";
31
- - in electron watches and refreshes (no per file reloading)
32
- - in chrome extension
33
- - errors if called in content script (must be called in background script)
34
- - reloads extension
35
- - option to refresh content script pages in overall watch function
36
- - On load, if reloaded in the last 10s, tells any pages which loaded content script to refresh their page
37
-
38
- - HELPER bin to setup the project with:
39
- (Only if the files don't exist)
40
- tsconfig.json
41
- .gitignore
42
- .vscode (for format on save)
43
- .eslintrc.js
44
- .cursorrules
45
- Add dependencies to package.json
46
- (Any dependencies our helper project has should be dev dependencies)
47
- - typenode
48
- - socket-function
49
- - typesafecss
50
- - typedev
51
- add the basic entry points for Node.js, the browser, the browser HTML file, and even some files for a Chrome extension, and even for an Electron app.
52
- - We'll make Electron optional though, and so they'll have to manually install Electron if they want to make an Electron app. We can check for this and warn if they try to build electron without having electron installed.
53
- Add build and type commands to package.json
54
- - We have the binaries for the build commands, but adding them to packs.json makes it a lot more discoverable.
55
- - And it's just very good practice to add the type command to package.json. That way you could just say, what does this command do to the AI? and it'll tell you exactly what it does, instead of nesting
56
-
57
- EXPOSE our helpers in our main export, in an index.ts file?
58
- - Will this let us just import them? Hmm...
59
- 5) Test it in a new test repo
60
- - Test it with:
61
- single html browser site
62
- nodejs bundled running
63
- electron
64
- chrome extension
65
- - Make sure sourcemaps are preserved and work
66
- 5.1) Use the new project and bundler in voice-cloner
6
+ TODO:
7
+ - vscode extension as well
@@ -1,7 +1,7 @@
1
1
  import preact from "preact";
2
2
  import { getFileSystemPointer, storeFileSystemPointer } from "./fileSystemPointer";
3
3
  import { observable } from "mobx";
4
- import { observer } from "../web/observer";
4
+ import { observer } from "../render-utils/observer";
5
5
  import { cache, lazy } from "socket-function/src/caching";
6
6
  import { css, isNode } from "typesafecss";
7
7
  import { IStorageRaw } from "./IStorage";
@@ -2,7 +2,7 @@ import { throttleFunction } from "socket-function/src/misc";
2
2
  import { observable } from "mobx";
3
3
  import preact from "preact";
4
4
  import { css } from "typesafecss";
5
- import { observer } from "../web/observer";
5
+ import { observer } from "../render-utils/observer";
6
6
  import { formatTime } from "socket-function/src/formatting/format";
7
7
 
8
8
  let watchState = observable({
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "emitDeclarationOnly": true,
6
+ "outDir": "./render-utils",
7
+ "rootDir": "./render-utils"
8
+ },
9
+ "include": [
10
+ "render-utils/**/*.ts",
11
+ "render-utils/**/*.tsx"
12
+ ],
13
+ "exclude": [
14
+ "node_modules",
15
+ "*_venv"
16
+ ]
17
+ }
18
+
@@ -0,0 +1,37 @@
1
+ import * as preact from "preact";
2
+ import { observable } from "mobx";
3
+ import { observer } from "../render-utils/observer";
4
+ import { css, isNode } from "typesafecss";
5
+ import { list } from "socket-function/src/misc";
6
+ import { enableHotReloading } from "../builders/hotReload";
7
+
8
+ @observer
9
+ class App extends preact.Component {
10
+ synced = observable({
11
+ count: 0,
12
+ });
13
+
14
+ render() {
15
+ return (
16
+ <div className={css.pad2(20)}>
17
+ <h1>Hello from Web! 3</h1>
18
+ <p>Count: {this.synced.count}</p>
19
+ <button onClick={() => this.synced.count++}>
20
+ Increment
21
+ </button>
22
+ <div>
23
+ {list(1000).map(x => <div key={x}>{x}</div>)}
24
+ </div>
25
+ </div>
26
+ );
27
+ }
28
+ }
29
+
30
+ async function main() {
31
+ if (isNode()) return;
32
+ await enableHotReloading({ port: 9877 });
33
+ preact.render(<App />, document.getElementById("app")!);
34
+ }
35
+
36
+ main().catch(console.error);
37
+
package/web/index.html ADDED
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Web App</title>
6
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
7
+ <style>
8
+ * {
9
+ box-sizing: border-box;
10
+ overflow-wrap: break-word;
11
+ word-wrap: break-word;
12
+ word-break: break-word;
13
+ }
14
+ body {
15
+ margin: 0px;
16
+ padding: 0px;
17
+ background: hsl(0, 0%, 7%);
18
+ color: hsl(0, 0%, 100%);
19
+ font-family: 'Inter', system-ui, -apple-system, Segoe UI, Roboto, 'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', sans-serif;
20
+ }
21
+ body, button, textarea {
22
+ font-family: Inter;
23
+ font-size: 12px;
24
+ }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <div id="app"></div>
29
+ <script src="../browser.js"></script>
30
+ </body>
31
+ </html>
32
+
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes