@andrivet/z80-assembler 1.3.2 → 1.4.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 (197) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.json +35 -0
  4. package/.github/workflows/node.js.yml +47 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc +3 -0
  7. package/.vscode/extensions.json +7 -0
  8. package/README.md +53 -27
  9. package/apps/.gitkeep +0 -0
  10. package/apps/z80-assembler-app/.eslintrc.json +18 -0
  11. package/apps/z80-assembler-app/index.html +16 -0
  12. package/apps/z80-assembler-app/postcss.config.js +24 -0
  13. package/apps/z80-assembler-app/project.json +70 -0
  14. package/apps/z80-assembler-app/public/favicon.ico +0 -0
  15. package/apps/z80-assembler-app/public/logo.png +0 -0
  16. package/apps/z80-assembler-app/public/logo192.png +0 -0
  17. package/apps/z80-assembler-app/public/logo512.png +0 -0
  18. package/apps/z80-assembler-app/public/manifest.json +25 -0
  19. package/apps/z80-assembler-app/public/robots.txt +3 -0
  20. package/apps/z80-assembler-app/src/app/app.module.css +0 -0
  21. package/apps/z80-assembler-app/src/app/app.tsx +122 -0
  22. package/apps/z80-assembler-app/src/app/binary.tsx +39 -0
  23. package/apps/z80-assembler-app/src/app/editor.tsx +228 -0
  24. package/apps/z80-assembler-app/src/app/errors.tsx +31 -0
  25. package/apps/z80-assembler-app/src/app/footer.tsx +20 -0
  26. package/apps/z80-assembler-app/src/app/header.tsx +57 -0
  27. package/apps/z80-assembler-app/src/app/misc.ts +13 -0
  28. package/apps/z80-assembler-app/src/app/opcodes.tsx +335 -0
  29. package/apps/z80-assembler-app/src/assets/.gitkeep +0 -0
  30. package/apps/z80-assembler-app/src/assets/images/logo192.png +0 -0
  31. package/apps/z80-assembler-app/src/main.tsx +22 -0
  32. package/apps/z80-assembler-app/src/styles.css +8 -0
  33. package/apps/z80-assembler-app/tailwind.config.js +28 -0
  34. package/apps/z80-assembler-app/tsconfig.app.json +22 -0
  35. package/apps/z80-assembler-app/tsconfig.json +21 -0
  36. package/apps/z80-assembler-app/tsconfig.spec.json +23 -0
  37. package/apps/z80-assembler-app/vite.config.ts +64 -0
  38. package/assets/images/compile.png +0 -0
  39. package/assets/images/logo.png +0 -0
  40. package/assets/images/menu.png +0 -0
  41. package/assets/images/opcodes-load8.png +0 -0
  42. package/assets/images/opcodes.png +0 -0
  43. package/assets/images/open-dir.png +0 -0
  44. package/assets/images/z80-assembler-app.png +0 -0
  45. package/docs/assembly.md +551 -0
  46. package/docs/images/ZX81-0x00.png +0 -0
  47. package/docs/images/ZX81-0x0B.png +0 -0
  48. package/docs/images/ZX81-0x0C.png +0 -0
  49. package/docs/images/ZX81-0x0D.png +0 -0
  50. package/docs/images/ZX81-0x0E.png +0 -0
  51. package/docs/images/ZX81-0x0F.png +0 -0
  52. package/docs/images/ZX81-0x10.png +0 -0
  53. package/docs/images/ZX81-0x11.png +0 -0
  54. package/docs/images/ZX81-0x12.png +0 -0
  55. package/docs/images/ZX81-0x13.png +0 -0
  56. package/docs/images/ZX81-0x14.png +0 -0
  57. package/docs/images/ZX81-0x15.png +0 -0
  58. package/docs/images/ZX81-0x16.png +0 -0
  59. package/docs/images/ZX81-0x17.png +0 -0
  60. package/docs/images/ZX81-0x18.png +0 -0
  61. package/docs/images/ZX81-0x19.png +0 -0
  62. package/docs/images/ZX81-0x1A.png +0 -0
  63. package/docs/images/ZX81-0x1B.png +0 -0
  64. package/docs/images/ZX81-0x1C.png +0 -0
  65. package/docs/images/ZX81-0x1D.png +0 -0
  66. package/docs/images/ZX81-0x1E.png +0 -0
  67. package/docs/images/ZX81-0x1F.png +0 -0
  68. package/docs/images/ZX81-0x20.png +0 -0
  69. package/docs/images/ZX81-0x21.png +0 -0
  70. package/docs/images/ZX81-0x22.png +0 -0
  71. package/docs/images/ZX81-0x23.png +0 -0
  72. package/docs/images/ZX81-0x24.png +0 -0
  73. package/docs/images/ZX81-0x25.png +0 -0
  74. package/docs/images/ZX81-0x26.png +0 -0
  75. package/docs/images/ZX81-0x27.png +0 -0
  76. package/docs/images/ZX81-0x28.png +0 -0
  77. package/docs/images/ZX81-0x29.png +0 -0
  78. package/docs/images/ZX81-0x2A.png +0 -0
  79. package/docs/images/ZX81-0x2B.png +0 -0
  80. package/docs/images/ZX81-0x2C.png +0 -0
  81. package/docs/images/ZX81-0x2D.png +0 -0
  82. package/docs/images/ZX81-0x2E.png +0 -0
  83. package/docs/images/ZX81-0x2F.png +0 -0
  84. package/docs/images/ZX81-0x30.png +0 -0
  85. package/docs/images/ZX81-0x31.png +0 -0
  86. package/docs/images/ZX81-0x32.png +0 -0
  87. package/docs/images/ZX81-0x33.png +0 -0
  88. package/docs/images/ZX81-0x34.png +0 -0
  89. package/docs/images/ZX81-0x35.png +0 -0
  90. package/docs/images/ZX81-0x36.png +0 -0
  91. package/docs/images/ZX81-0x37.png +0 -0
  92. package/docs/images/ZX81-0x38.png +0 -0
  93. package/docs/images/ZX81-0x39.png +0 -0
  94. package/docs/images/ZX81-0x3A.png +0 -0
  95. package/docs/images/ZX81-0x3B.png +0 -0
  96. package/docs/images/ZX81-0x3C.png +0 -0
  97. package/docs/images/ZX81-0x3D.png +0 -0
  98. package/docs/images/ZX81-0x3E.png +0 -0
  99. package/docs/images/ZX81-0x3F.png +0 -0
  100. package/docs/images/ZX81-0x80.png +0 -0
  101. package/docs/images/ZX81-0x8B.png +0 -0
  102. package/docs/images/ZX81-0x8C.png +0 -0
  103. package/docs/images/ZX81-0x8D.png +0 -0
  104. package/docs/images/ZX81-0x8E.png +0 -0
  105. package/docs/images/ZX81-0x8F.png +0 -0
  106. package/docs/images/ZX81-0x90.png +0 -0
  107. package/docs/images/ZX81-0x91.png +0 -0
  108. package/docs/images/ZX81-0x92.png +0 -0
  109. package/docs/images/ZX81-0x93.png +0 -0
  110. package/docs/images/ZX81-0x94.png +0 -0
  111. package/docs/images/ZX81-0x95.png +0 -0
  112. package/docs/images/ZX81-0x96.png +0 -0
  113. package/docs/images/ZX81-0x97.png +0 -0
  114. package/docs/images/ZX81-0x98.png +0 -0
  115. package/docs/images/ZX81-0x99.png +0 -0
  116. package/docs/images/ZX81-0x9A.png +0 -0
  117. package/docs/images/ZX81-0x9B.png +0 -0
  118. package/docs/images/ZX81-0x9C.png +0 -0
  119. package/docs/images/ZX81-0x9D.png +0 -0
  120. package/docs/images/ZX81-0x9E.png +0 -0
  121. package/docs/images/ZX81-0x9F.png +0 -0
  122. package/docs/images/ZX81-0xA0.png +0 -0
  123. package/docs/images/ZX81-0xA1.png +0 -0
  124. package/docs/images/ZX81-0xA2.png +0 -0
  125. package/docs/images/ZX81-0xA3.png +0 -0
  126. package/docs/images/ZX81-0xA4.png +0 -0
  127. package/docs/images/ZX81-0xA5.png +0 -0
  128. package/docs/images/ZX81-0xA6.png +0 -0
  129. package/docs/images/ZX81-0xA7.png +0 -0
  130. package/docs/images/ZX81-0xA8.png +0 -0
  131. package/docs/images/ZX81-0xA9.png +0 -0
  132. package/docs/images/ZX81-0xAA.png +0 -0
  133. package/docs/images/ZX81-0xAB.png +0 -0
  134. package/docs/images/ZX81-0xAC.png +0 -0
  135. package/docs/images/ZX81-0xAD.png +0 -0
  136. package/docs/images/ZX81-0xAE.png +0 -0
  137. package/docs/images/ZX81-0xAF.png +0 -0
  138. package/docs/images/ZX81-0xB0.png +0 -0
  139. package/docs/images/ZX81-0xB1.png +0 -0
  140. package/docs/images/ZX81-0xB2.png +0 -0
  141. package/docs/images/ZX81-0xB3.png +0 -0
  142. package/docs/images/ZX81-0xB4.png +0 -0
  143. package/docs/images/ZX81-0xB5.png +0 -0
  144. package/docs/images/ZX81-0xB6.png +0 -0
  145. package/docs/images/ZX81-0xB7.png +0 -0
  146. package/docs/images/ZX81-0xB8.png +0 -0
  147. package/docs/images/ZX81-0xB9.png +0 -0
  148. package/docs/images/ZX81-0xBA.png +0 -0
  149. package/docs/images/ZX81-0xBB.png +0 -0
  150. package/docs/images/ZX81-0xBC.png +0 -0
  151. package/docs/images/ZX81-0xBD.png +0 -0
  152. package/docs/images/ZX81-0xBE.png +0 -0
  153. package/docs/images/ZX81-0xBF.png +0 -0
  154. package/libs/.gitkeep +0 -0
  155. package/libs/z80-assembler/.eslintrc.json +18 -0
  156. package/libs/z80-assembler/package.json +20 -0
  157. package/libs/z80-assembler/project.json +35 -0
  158. package/libs/z80-assembler/public/README.md +54 -0
  159. package/{index.d.ts → libs/z80-assembler/src/index.ts} +1 -1
  160. package/libs/z80-assembler/src/lib/assets/code/basic-end.zx81 +4 -0
  161. package/libs/z80-assembler/src/lib/assets/code/basic-line1.zx81 +4 -0
  162. package/libs/z80-assembler/src/lib/assets/code/basic-line2.zx81 +9 -0
  163. package/libs/z80-assembler/src/lib/assets/code/characters.zx81 +190 -0
  164. package/libs/z80-assembler/src/lib/assets/code/display.zx81 +50 -0
  165. package/libs/z80-assembler/src/lib/assets/code/system-variables.zx81 +46 -0
  166. package/{lib/compiler/Assets.d.ts → libs/z80-assembler/src/lib/compiler/Assets.ts} +6 -1
  167. package/libs/z80-assembler/src/lib/compiler/Ast.ts +545 -0
  168. package/libs/z80-assembler/src/lib/compiler/Compiler.test.ts +2141 -0
  169. package/libs/z80-assembler/src/lib/compiler/Compiler.ts +185 -0
  170. package/libs/z80-assembler/src/lib/compiler/Formatter.ts +43 -0
  171. package/libs/z80-assembler/src/lib/compiler/Generator.ts +255 -0
  172. package/libs/z80-assembler/src/lib/compiler/Labels.ts +165 -0
  173. package/libs/z80-assembler/src/lib/grammar/LowLevel.ts +163 -0
  174. package/libs/z80-assembler/src/lib/grammar/Parse.ts +128 -0
  175. package/libs/z80-assembler/src/lib/grammar/z80.peg +1252 -0
  176. package/libs/z80-assembler/src/lib/grammar/z80.ts +10649 -0
  177. package/libs/z80-assembler/src/lib/types/Error.ts +105 -0
  178. package/{lib/types/Types.d.ts → libs/z80-assembler/src/lib/types/Types.ts} +26 -11
  179. package/libs/z80-assembler/tsconfig.json +23 -0
  180. package/libs/z80-assembler/tsconfig.lib.json +10 -0
  181. package/libs/z80-assembler/tsconfig.spec.json +19 -0
  182. package/libs/z80-assembler/vite.config.ts +58 -0
  183. package/nx.json +57 -0
  184. package/package.json +52 -14
  185. package/tsconfig.base.json +22 -0
  186. package/index.js +0 -312
  187. package/index.mjs +0 -6441
  188. package/lib/compiler/Ast.d.ts +0 -210
  189. package/lib/compiler/Compiler.d.ts +0 -53
  190. package/lib/compiler/Formatter.d.ts +0 -23
  191. package/lib/compiler/Generator.d.ts +0 -40
  192. package/lib/compiler/Labels.d.ts +0 -47
  193. package/lib/grammar/LowLevel.d.ts +0 -68
  194. package/lib/grammar/Parse.d.ts +0 -48
  195. package/lib/grammar/z80.d.ts +0 -2938
  196. package/lib/types/Error.d.ts +0 -62
  197. /package/{CHANGELOG.md → libs/z80-assembler/public/CHANGELOG.md} +0 -0
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Z80 Assembler in Typescript
3
+ *
4
+ * File: editor.tsx
5
+ * Description: Code editor
6
+ * Author: Sebastien Andrivet
7
+ * License: GPLv3
8
+ * Copyrights: Copyright (C) 2023 Sebastien Andrivet
9
+ */
10
+ import {Tabs} from "react-daisyui";
11
+ import {FaWindowClose} from "react-icons/fa";
12
+ import CodeMirror, {basicSetup} from "@uiw/react-codemirror";
13
+ import {linter, lintGutter} from '@codemirror/lint'
14
+ import React, {useState, useImperativeHandle} from "react";
15
+ import {directoryOpen, fileOpen, fileSave, FileWithDirectoryAndFileHandle} from "browser-fs-access";
16
+ import {closeDropdown} from "./misc";
17
+ import {CompilationError} from "@andrivet/z80-assembler";
18
+
19
+ const validExt = ['.asm', '.zx81'];
20
+
21
+ interface AppEditorHandlers {
22
+ openCode: () => void;
23
+ openCodeDirectory: () => void;
24
+ saveCode: () => void;
25
+ closeCode: () => void;
26
+ closeAll: () => void;
27
+ getCode: (filename: string) => string;
28
+ }
29
+
30
+ interface AppEditorProps {
31
+ code: string,
32
+ setFilePath: React.Dispatch<React.SetStateAction<string>>,
33
+ setCode: React.Dispatch<React.SetStateAction<string>>,
34
+ errors: CompilationError[] | undefined,
35
+ setErrors: React.Dispatch<React.SetStateAction<CompilationError[] | undefined>>
36
+ }
37
+
38
+ type CodeFile = {
39
+ filepath: string,
40
+ name: string | undefined,
41
+ code: string
42
+ };
43
+
44
+ function getExt(name: string) {
45
+ return /(?:\.([^.]+))?$/.exec(name);
46
+ }
47
+
48
+ function isValidExt(name: string){
49
+ const ext = getExt(name)?.[1];
50
+ if(!ext) return false;
51
+ return validExt.indexOf('.' + ext) !== -1
52
+ }
53
+
54
+
55
+ function AppEditor(props: AppEditorProps, ref: React.ForwardedRef<AppEditorHandlers>) {
56
+ const [codeFiles, setCodeFiles] = useState<CodeFile[]>([{filepath: '', name: undefined, code: ''}]);
57
+ const [currentFile, setCurrentFile] = useState<number>(0);
58
+
59
+ async function handleOpenCode() {
60
+ const blob = await fileOpen({extensions: validExt});
61
+ closeDropdown();
62
+ const content = await blob.text();
63
+
64
+ let files: CodeFile[];
65
+ let current = codeFiles[currentFile];
66
+ if(current.name == null && current.code.length <= 0) {
67
+ files = [...codeFiles]; // Have to be a copy
68
+ current = files[currentFile];
69
+ current.filepath = blob.name;
70
+ current.name = blob.name;
71
+ current.code = content;
72
+ }
73
+ else
74
+ files = [...codeFiles, {filepath: blob.name, name: blob.name, code: content}]; // Must be a copy
75
+
76
+ setCodeFiles(files);
77
+ setCurrentFile(files.length - 1);
78
+ props.setCode(content);
79
+ props.setFilePath(blob.name);
80
+ props.setErrors(undefined);
81
+ }
82
+
83
+ async function handleOpenDirectory() {
84
+ const blobs = await directoryOpen({
85
+ recursive: true
86
+ });
87
+ closeDropdown();
88
+
89
+ const files = [...codeFiles]; // Have to be a copy
90
+ for (const blob of blobs) {
91
+ if (!isValidExt(blob.name)) continue;
92
+ const file = blob as FileWithDirectoryAndFileHandle;
93
+ const content = await file.text();
94
+ files.push({filepath: file.webkitRelativePath, name: blob.name, code: content});
95
+ }
96
+ const index = files.length - 1;
97
+ setCodeFiles(files);
98
+ setCurrentFile(index);
99
+ props.setCode(files[index].code);
100
+ props.setFilePath(files[index].filepath);
101
+ props.setErrors(undefined);
102
+ }
103
+
104
+ async function handleSaveCode() {
105
+ closeDropdown();
106
+ const file = codeFiles[currentFile];
107
+ if (!file) return;
108
+ const blob = new Blob([file.code]);
109
+ await fileSave(blob, {
110
+ fileName: file.name ?? 'untitled.asm',
111
+ extensions: validExt
112
+ });
113
+ }
114
+
115
+ function handleGetCode(filename: string) {
116
+ const file = codeFiles.find(f => f.filepath.endsWith(filename));
117
+ if(file == null) throw new Error(`File ${filename} not found`);
118
+ return file.code;
119
+ }
120
+
121
+ function handleCloseCode() {
122
+ closeDropdown();
123
+ handleCloseTab(currentFile);
124
+ }
125
+
126
+ function handleCloseAll() {
127
+ closeDropdown();
128
+ setCodeFiles([{filepath: '', name: undefined, code: ''}]);
129
+ setCurrentFile(0);
130
+ props.setCode('');
131
+ props.setFilePath('');
132
+ props.setErrors(undefined);
133
+ }
134
+
135
+ useImperativeHandle(ref, () => {
136
+ return {
137
+ openCode: handleOpenCode,
138
+ openCodeDirectory: handleOpenDirectory,
139
+ saveCode: handleSaveCode,
140
+ getCode: handleGetCode,
141
+ closeCode: handleCloseCode,
142
+ closeAll: handleCloseAll
143
+ }
144
+ });
145
+
146
+ function handleChangeTab(index: number) {
147
+ if (index >= codeFiles.length) index = codeFiles.length > 0 ? codeFiles.length - 1 : 0;
148
+ setCurrentFile(index);
149
+ if(codeFiles.length > 0) {
150
+ const file = codeFiles[index];
151
+ props.setCode(file.code);
152
+ props.setFilePath(file.filepath);
153
+ }
154
+ else {
155
+ props.setCode('');
156
+ props.setFilePath('');
157
+ }
158
+ props.setErrors(undefined);
159
+ }
160
+
161
+ function handleCloseTab(index: number) {
162
+ const files = codeFiles.slice(0, index).concat(codeFiles.slice(index + 1));
163
+ if(files.length <= 0) {
164
+ setCodeFiles([{filepath: '', name: undefined, code: ''}]);
165
+ setCurrentFile(0);
166
+ props.setCode('');
167
+ props.setFilePath('');
168
+ props.setErrors(undefined);
169
+ }
170
+ else {
171
+ setCodeFiles(files);
172
+ if (index >= files.length) index = files.length - 1;
173
+ setCurrentFile(index);
174
+ const file = files[index];
175
+ props.setCode(file.code);
176
+ props.setFilePath(file.filepath);
177
+ props.setErrors(undefined);
178
+ }
179
+ }
180
+
181
+ const asmLinter = linter(view => {
182
+ return props.errors == null ? [] : props.errors
183
+ ?.filter(value => codeFiles[currentFile].filepath === value.position.filename)
184
+ .map(value => {
185
+ const from = view.state.doc.line(value.position.pos.line).from + value.position.pos.offset;
186
+ return {
187
+ from: from,
188
+ to: from + 1,
189
+ severity: "error",
190
+ message: value.message
191
+ }
192
+ })
193
+ });
194
+
195
+ return(
196
+ <>
197
+ <h1 className="font-bold mb-2 text-orange-400">Assembler Code</h1>
198
+ <div className="flex flex-col flex-1">
199
+ <Tabs
200
+ variant={"lifted"}
201
+ value={currentFile}
202
+ >{
203
+ codeFiles.map((file, index) => (
204
+ <Tabs.Tab key={index} value={index}>
205
+ <FaWindowClose
206
+ className="h-4 w-4 mr-2"
207
+ onClick={() => handleCloseTab(index)} />
208
+ <p onClick={() => handleChangeTab(index)}>{file.name ?? 'untitled.asm'}</p>
209
+ </Tabs.Tab>
210
+ ))}
211
+ </Tabs>
212
+ <div className="flex flex-auto h-full relative mt-0">
213
+ <CodeMirror
214
+ className="absolute top-0 bottom-0 left-0 right-0"
215
+ theme="dark"
216
+ height="100%"
217
+ value={props.code}
218
+ onChange={(value) => props.setCode(value)}
219
+ extensions={[basicSetup(), asmLinter, lintGutter()]}
220
+ />
221
+ </div>
222
+ </div>
223
+ </>
224
+ );
225
+ }
226
+
227
+ export default React.forwardRef(AppEditor);
228
+ export {AppEditorHandlers};
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Z80 Assembler in Typescript
3
+ *
4
+ * File: errors.tsx
5
+ * Description: Compilation errors
6
+ * Author: Sebastien Andrivet
7
+ * License: GPLv3
8
+ * Copyrights: Copyright (C) 2023 Sebastien Andrivet
9
+ */
10
+ import {CompilationError} from "@andrivet/z80-assembler";
11
+
12
+ interface ErrorsProps {
13
+ errors: CompilationError[] | undefined;
14
+ }
15
+
16
+ function errorText(errors: CompilationError[] | undefined) {
17
+ if(errors == null) return '';
18
+ if(errors.length <= 0) return 'Successful compilation';
19
+ return errors[0].toString();
20
+ }
21
+
22
+ function Errors({errors}: ErrorsProps) {
23
+ const hasError = errors && errors?.length > 0;
24
+ const text = errorText(errors);
25
+ return (
26
+ <div className=" h-8 mx-3 mb-4">
27
+ <p className={`px-2 pt-0.5 ${hasError ? 'text-red-300' : ' text-green-300'}`}>{text}</p>
28
+ </div>);
29
+ }
30
+
31
+ export default Errors;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Z80 Assembler in Typescript
3
+ *
4
+ * File: footer.tsx
5
+ * Description: Footer of the application
6
+ * Author: Sebastien Andrivet
7
+ * License: GPLv3
8
+ * Copyrights: Copyright (C) 2023 Sebastien Andrivet
9
+ */
10
+ import {Footer} from "react-daisyui";
11
+ import React from "react";
12
+
13
+ export default function AppFooter() {
14
+ return (
15
+ <div className="flex-none">
16
+ <Footer className="footer-center sticky mb-0 py-2 bg-neutral-700">
17
+ <a href='https://www.github.com/andrivet/z80-assembler'>Z80 Assembler in Typescript - Copyright &copy; 2023 Sebastien Andrivet</a>
18
+ </Footer>
19
+ </div>);
20
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Z80 Assembler in Typescript
3
+ *
4
+ * File: header.tsx
5
+ * Description: Header of the application
6
+ * Author: Sebastien Andrivet
7
+ * License: GPLv3
8
+ * Copyrights: Copyright (C) 2023 Sebastien Andrivet
9
+ */
10
+ import React from "react";
11
+ import {Button, Dropdown, Navbar} from "react-daisyui";
12
+ import logoUrl from "../assets/images/logo192.png";
13
+ import {FaChevronDown, FaCog, FaFile, FaFileAlt, FaCodepen, FaFolderOpen, FaSave, FaTimesCircle} from "react-icons/fa";
14
+
15
+
16
+ interface AppHeaderProps {
17
+ onOpenCode: () => void;
18
+ onOpenCodeDirectory: () => void;
19
+ onSaveCode: () => void;
20
+ onSaveBinary: () => void;
21
+ onSaveSld: () => void;
22
+ onCompile: () => void;
23
+ onShowOpCodes: () => void;
24
+ onClose: () => void;
25
+ onCloseAll: () => void;
26
+ }
27
+
28
+ export default function AppHeader(props: AppHeaderProps) {
29
+
30
+ return (
31
+ <div className="flex-none">
32
+ <Navbar className="bg-neutral-700 top-0">
33
+ <Navbar.Start>
34
+ <img src={logoUrl} width={32} className="mx-4" alt="Logo"></img><span className="text-orange-400">Z80 Assembler</span>
35
+ </Navbar.Start>
36
+ <Navbar.Center className="flex">
37
+ <Dropdown hover={true} className="z-10">
38
+ <Dropdown.Toggle color="ghost"><FaFile className="h-5 w-5" />File<FaChevronDown className="w-4 h-4" /></Dropdown.Toggle>
39
+ <Dropdown.Menu className="w-56">
40
+ <Dropdown.Item onClick={props.onOpenCode}><FaFileAlt className="h-5 w-5" />Open Code...</Dropdown.Item>
41
+ <Dropdown.Item onClick={props.onOpenCodeDirectory}><FaFolderOpen className="h-5 w-5" />Open Code Directory...</Dropdown.Item>
42
+ <Dropdown.Item onClick={props.onSaveCode}><FaSave className="h-5 w-5" />Save Code...</Dropdown.Item>
43
+ <Dropdown.Item onClick={props.onSaveBinary}><FaSave className="h-5 w-5" />Save Binary...</Dropdown.Item>
44
+ <Dropdown.Item onClick={props.onSaveSld}><FaSave className="h-5 w-5" />Save SLD File...</Dropdown.Item>
45
+ <Dropdown.Item onClick={props.onClose}><FaTimesCircle className="h-5 w-5" />Close Code</Dropdown.Item>
46
+ <Dropdown.Item onClick={props.onCloseAll}><FaTimesCircle className="h-5 w-5" />Close All</Dropdown.Item>
47
+ </Dropdown.Menu>
48
+ </Dropdown>
49
+ <Button color="ghost" onClick={props.onCompile}><FaCog className="h-5 w-5"/>Compile</Button>
50
+ </Navbar.Center>
51
+ <Navbar.End>
52
+ <Button color="ghost" onClick={props.onShowOpCodes}><FaCodepen className="h-5 w-5" />Z80 Opcodes</Button>
53
+ </Navbar.End>
54
+ </Navbar>
55
+ </div>
56
+ );
57
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Z80 Assembler in Typescript
3
+ *
4
+ * File: misc.ts
5
+ * Description: Helpers
6
+ * Author: Sebastien Andrivet
7
+ * License: GPLv3
8
+ * Copyrights: Copyright (C) 2023 Sebastien Andrivet
9
+ */
10
+ export function closeDropdown() {
11
+ const elem = document.activeElement as HTMLElement;
12
+ if(elem) elem?.blur();
13
+ }