lhasa-ligand-builder 0.1.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 (67) hide show
  1. package/.eslintrc.cjs +18 -0
  2. package/LICENSE +674 -0
  3. package/README.md +41 -0
  4. package/index.html +49 -0
  5. package/package.json +37 -0
  6. package/public/.gitkeep +0 -0
  7. package/public/Components-inchikey.ich +48167 -0
  8. package/public/icons/README +7 -0
  9. package/public/icons/dark/layla_3c.svg +82 -0
  10. package/public/icons/dark/layla_4c.svg +82 -0
  11. package/public/icons/dark/layla_5c.svg +82 -0
  12. package/public/icons/dark/layla_6arom.svg +89 -0
  13. package/public/icons/dark/layla_6c.svg +82 -0
  14. package/public/icons/dark/layla_7c.svg +82 -0
  15. package/public/icons/dark/layla_8c.svg +82 -0
  16. package/public/icons/dark/layla_charge_tool.svg +78 -0
  17. package/public/icons/dark/layla_delete_hydrogens_tool.svg +384 -0
  18. package/public/icons/dark/layla_double_bond.svg +78 -0
  19. package/public/icons/dark/layla_format_tool.svg +283 -0
  20. package/public/icons/dark/layla_geometry_tool.svg +105 -0
  21. package/public/icons/dark/layla_key.svg +76 -0
  22. package/public/icons/dark/layla_move_tool.svg +110 -0
  23. package/public/icons/dark/layla_single_bond.svg +73 -0
  24. package/public/icons/dark/layla_triple_bond.svg +87 -0
  25. package/public/icons/dark/lhasa_delete_tool.svg +401 -0
  26. package/public/icons/dark/lhasa_flip_x_tool.svg +106 -0
  27. package/public/icons/dark/lhasa_flip_y_tool.svg +106 -0
  28. package/public/icons/dark/lhasa_rotate_tool.svg +112 -0
  29. package/public/icons/icons/hicolor_apps_scalable_coot-layla.svg +105 -0
  30. package/public/icons/layla_3c.svg +82 -0
  31. package/public/icons/layla_4c.svg +82 -0
  32. package/public/icons/layla_5c.svg +82 -0
  33. package/public/icons/layla_6arom.svg +89 -0
  34. package/public/icons/layla_6c.svg +82 -0
  35. package/public/icons/layla_7c.svg +82 -0
  36. package/public/icons/layla_8c.svg +82 -0
  37. package/public/icons/layla_charge_tool.svg +78 -0
  38. package/public/icons/layla_delete_hydrogens_tool.svg +384 -0
  39. package/public/icons/layla_double_bond.svg +78 -0
  40. package/public/icons/layla_format_tool.svg +283 -0
  41. package/public/icons/layla_geometry_tool-dark.svg +105 -0
  42. package/public/icons/layla_geometry_tool.svg +105 -0
  43. package/public/icons/layla_key.svg +76 -0
  44. package/public/icons/layla_move_tool.svg +110 -0
  45. package/public/icons/layla_single_bond.svg +73 -0
  46. package/public/icons/layla_triple_bond.svg +87 -0
  47. package/public/icons/lhasa_delete_tool.svg +401 -0
  48. package/public/icons/lhasa_flip_x_tool.svg +106 -0
  49. package/public/icons/lhasa_flip_y_tool.svg +106 -0
  50. package/public/icons/lhasa_rotate_tool.svg +112 -0
  51. package/public/lhasa.js +2 -0
  52. package/public/lhasa.wasm +0 -0
  53. package/public/react.svg +1 -0
  54. package/src/Lhasa.tsx +1452 -0
  55. package/src/assets/.gitkeep +0 -0
  56. package/src/bansu_integration.tsx +315 -0
  57. package/src/customize_mui.scss +97 -0
  58. package/src/inchikey_database_parse.tsx +20 -0
  59. package/src/index.d.ts +11 -0
  60. package/src/index.scss +352 -0
  61. package/src/main.tsx +79 -0
  62. package/src/qed_property_infobox.tsx +14 -0
  63. package/src/types.d.ts +375 -0
  64. package/src/vite-env.d.ts +1 -0
  65. package/tsconfig.json +25 -0
  66. package/tsconfig.node.json +10 -0
  67. package/vite.config.ts +55 -0
package/src/index.scss ADDED
@@ -0,0 +1,352 @@
1
+ @use 'sass:color';
2
+
3
+ $lhasa_background_color: rgba(119, 119, 119, 0.076);
4
+ $lhasa_background_color_dark: rgb(53, 53, 53);
5
+ $lhasa_text_color: black;
6
+ $lhasa_text_color_dark: white;
7
+ $lhasa_qed_value_color: color.adjust($lhasa_text_color, $saturation: +50%, $lightness: +50%, $hue: 196);
8
+ $lhasa_qed_value_color_dark: color.adjust($lhasa_text_color, $saturation: +75%, $lightness: +65%, $hue: 310);
9
+ $lhasa_border_color: rgba(0, 0, 0, 0.24);
10
+ $lhasa_border_color_dark: rgba(255, 255, 255, 0.24);
11
+ $lhasa_toolbar_border_color: rgba(184, 0, 0, 0.181);
12
+ $lhasa_toolbar_border_color_dark: rgba(250, 85, 85, 0.281);
13
+ $lhasa_base_padding: 3px;
14
+ $lhasa_padding_minor: 2px;
15
+ $lhasa_font_size: 0.65rem;
16
+
17
+ .editor_canvas_container {
18
+ border: $lhasa_border_color 1px solid;
19
+ /* Padding here breaks relative coords */
20
+ /* padding: 5px; */
21
+ cursor: default;
22
+ user-select: none;
23
+ overflow: auto;
24
+ width: 480px;
25
+ height: 270px;
26
+ // max-width: 700px;
27
+ // min-width: 300px;
28
+ // max-height: 500px;
29
+ // min-height: 320px;
30
+ }
31
+
32
+ .editor_canvas_container.lhasa_dark_mode {
33
+ border-color: $lhasa_border_color_dark;
34
+ }
35
+
36
+ .lhasa_drawing {
37
+ background-color: white;
38
+ /* Removes weird, empty margin-like area */
39
+ margin-bottom: -$lhasa_base_padding;
40
+ // Disable default scroll on touch behaviour
41
+ touch-action: none;
42
+ }
43
+
44
+ .lhasa_editor {
45
+ font-family: sans-serif;
46
+ background-color: $lhasa_background_color;
47
+ color: $lhasa_text_color;
48
+ font-size: $lhasa_font_size;
49
+ padding: 2 * $lhasa_base_padding;
50
+ width: fit-content;
51
+ text-align: left;
52
+ }
53
+
54
+ .lhasa_editor.lhasa_dark_mode {
55
+ background-color: $lhasa_background_color_dark;
56
+ color: $lhasa_text_color_dark;
57
+ }
58
+
59
+ // For the menus
60
+ .keybind_hint {
61
+ color: color.adjust($lhasa_text_color, $saturation: -50%, $lightness: +40%);
62
+ background-color: $lhasa_background_color;
63
+ margin-left: $lhasa_base_padding;
64
+ border-radius: $lhasa_padding_minor;
65
+ padding: $lhasa_padding_minor;
66
+ // font-family: monospace;
67
+ }
68
+
69
+ .lhasa_dark_mode .keybind_hint {
70
+ background-color: $lhasa_background_color_dark;
71
+ color: color.adjust($lhasa_text_color_dark, $saturation: -20%, $lightness: -40%);
72
+ // color: pink;
73
+ }
74
+
75
+ .lhasa_tooltip_keybind_infoblock {
76
+ padding: $lhasa_base_padding * 2;
77
+ margin-top: $lhasa_base_padding;
78
+ border-radius: 3px;
79
+ // This border color works well in both modes
80
+ border: rgba(255, 255, 255, 0.405) 1px solid;
81
+ }
82
+
83
+ .lhasa_tooltip_keybind_info {
84
+ margin: $lhasa_base_padding;
85
+ // font-size: medium;
86
+ // margin-top: $lhasa_base_padding * 8;
87
+ border-radius: 3px;
88
+ color: lightblue;
89
+ background-color: color.adjust(lightblue, $alpha: -0.8);
90
+ padding: $lhasa_base_padding;
91
+ }
92
+
93
+ .lhasa_tooltip {
94
+ font-size: small;
95
+ font-family: sans-serif;
96
+ margin: $lhasa_base_padding * 2;
97
+ // color: red !important;
98
+ }
99
+
100
+ @mixin toolbar {
101
+ border: $lhasa_toolbar_border_color 1px solid;
102
+ border-radius: 3px;
103
+ padding: $lhasa_base_padding;
104
+ /* align-items: center; */
105
+ }
106
+
107
+ @mixin toolbar_dark {
108
+ border-color: $lhasa_toolbar_border_color_dark;
109
+ }
110
+
111
+ @mixin panel {
112
+ border: $lhasa_border_color 1px solid;
113
+ border-radius: 3px;
114
+ padding: $lhasa_base_padding;
115
+ }
116
+
117
+ @mixin panel_dark {
118
+ border-color: $lhasa_border_color_dark;
119
+ }
120
+
121
+ .scale_panel {
122
+ flex-grow: 1;
123
+ }
124
+
125
+ .invalid_molecules_panel,
126
+ .display_mode_panel,
127
+ .status_display_panel {
128
+ margin-bottom: $lhasa_base_padding;
129
+ }
130
+
131
+ .x_element_panel {
132
+ margin-bottom: $lhasa_base_padding;
133
+ /* display: none; */
134
+ }
135
+
136
+
137
+ @mixin horizontal_flex {
138
+ display: flex;
139
+ flex-direction: row;
140
+ }
141
+
142
+ @mixin vertical_flex {
143
+ display: flex;
144
+ flex-direction: column;
145
+ }
146
+
147
+ @mixin lhasa_disable_MUI_swelling {
148
+ font-size: $lhasa_font_size;
149
+ line-height: normal;
150
+ letter-spacing: 0em;
151
+ }
152
+
153
+ @mixin center_flex {
154
+ text-align: center;
155
+ justify-content: center;
156
+ /* CSS is weird */
157
+ align-items: center;
158
+ }
159
+
160
+ @mixin horizontal_container {
161
+ @include horizontal_flex;
162
+ gap: $lhasa_base_padding;
163
+ }
164
+
165
+ .horizontal_container {
166
+ @include horizontal_container;
167
+ }
168
+
169
+ .horizontal_container_centered {
170
+ @include horizontal_container;
171
+ @include center_flex;
172
+ }
173
+
174
+ .children_expanded > * {
175
+ flex-grow: 1;
176
+ }
177
+
178
+ @mixin vertical_container {
179
+ @include vertical_flex;
180
+ gap: $lhasa_base_padding;
181
+ }
182
+
183
+ .horizontal_toolbar {
184
+ @include toolbar;
185
+ @include horizontal_container;
186
+ margin-bottom: $lhasa_padding_minor;
187
+ margin-top: $lhasa_padding_minor;
188
+ }
189
+
190
+ .lhasa_dark_mode .horizontal_toolbar {
191
+ @include toolbar_dark;
192
+ }
193
+
194
+ .vertical_toolbar {
195
+ @include toolbar;
196
+ @include vertical_container;
197
+ /* margin-right: 2px;
198
+ margin-left: 2px; */
199
+ align-items: normal;
200
+ }
201
+
202
+ .lhasa_dark_mode .vertical_toolbar {
203
+ @include toolbar_dark;
204
+ }
205
+
206
+ .vertical_panel {
207
+ @include vertical_container;
208
+ @include panel;
209
+ }
210
+
211
+ .lhasa_dark_mode .vertical_panel {
212
+ @include panel_dark;
213
+ }
214
+
215
+ .horizontal_panel {
216
+ @include horizontal_container;
217
+ @include panel;
218
+ }
219
+
220
+ .lhasa_dark_mode .horizontal_panel {
221
+ @include panel_dark;
222
+ }
223
+
224
+ .lhasa_icon {
225
+ width: 18px;
226
+ }
227
+
228
+ .tool_button {
229
+ @include vertical_container;
230
+ @include center_flex;
231
+ @include lhasa_disable_MUI_swelling;
232
+ gap: $lhasa_padding_minor;
233
+ padding: $lhasa_base_padding;
234
+ }
235
+
236
+ .vertical_popup {
237
+ @include vertical_container;
238
+ @include center_flex;
239
+ gap: $lhasa_padding_minor * 4;
240
+ padding: $lhasa_base_padding * 4;
241
+ }
242
+
243
+ .vertical_popup_title {
244
+ @include horizontal_container;
245
+ font-size: larger;
246
+ font-weight: bold;
247
+ // todo: dark_theme
248
+ border-bottom: color.adjust($lhasa_toolbar_border_color, $saturation: +90%, $lightness: -0%, $alpha: +0.7) 2px solid;
249
+ margin-bottom: $lhasa_base_padding;
250
+ // border-radius: 4px;
251
+ // padding: $lhasa_base_padding;
252
+ flex-grow: 1;
253
+ justify-content: center;
254
+ align-self: normal;
255
+ }
256
+
257
+ .lhasa_dark_mode .vertical_popup_title {
258
+ border-color: color.adjust($lhasa_toolbar_border_color_dark, $saturation: +90%, $lightness: -0%, $alpha: +0.7);
259
+ }
260
+
261
+ .smiles_display {
262
+ padding: $lhasa_base_padding;
263
+ font-family: monospace;
264
+ margin-bottom: $lhasa_base_padding * 2;
265
+ }
266
+
267
+ .scale_display {
268
+ flex-grow: 1;
269
+ margin-left: $lhasa_base_padding * 4;
270
+ }
271
+
272
+ .status_display_panel,
273
+ .qed_panel {
274
+ padding: 2 * $lhasa_base_padding;
275
+ margin-top: $lhasa_base_padding;
276
+ }
277
+
278
+ .qed_property_value {
279
+ color: $lhasa_qed_value_color;
280
+ margin-left: $lhasa_padding_minor;
281
+ font-weight: bold;
282
+ }
283
+
284
+ .lhasa_dark_mode .qed_property_value {
285
+ color: $lhasa_qed_value_color_dark;
286
+ }
287
+
288
+ .qed_property_label {
289
+ font-weight: bolder;
290
+ }
291
+
292
+ .lhasa_editor input {
293
+ font-family: sans-serif;
294
+ background-color: $lhasa_background_color;
295
+ color: $lhasa_text_color;
296
+ font-size: $lhasa_font_size;
297
+ border-style: ridge;
298
+ }
299
+
300
+ .lhasa_editor.lhasa_dark_mode input {
301
+ background-color: $lhasa_background_color_dark;
302
+ // border-color: $lhasa_toolbar_border_color_dark;
303
+ color: $lhasa_text_color_dark;
304
+ // this is broken
305
+ // /* Apply infinite transition to block autofill styles */
306
+ // // transition: background-color 9999s, color 9999s;
307
+ }
308
+
309
+ //Fix 'internal-autofill-selected' whitish background in Chrome
310
+ .lhasa_editor.lhasa_dark_mode input:-webkit-autofill {
311
+ -webkit-box-shadow: 0 0 0px 1000px $lhasa_background_color inset !important;
312
+ box-shadow: 0 0 0px 1000px $lhasa_background_color_dark inset !important;
313
+ -webkit-text-fill-color: $lhasa_text_color_dark !important;
314
+ }
315
+
316
+ .smiles_input {
317
+ flex-grow: 1;
318
+ }
319
+
320
+ .lhasa_footer {
321
+ margin-top: 4 * $lhasa_base_padding;
322
+ }
323
+
324
+ .pre_render_message {
325
+ color: $lhasa_text_color;
326
+ font-weight: bold;
327
+ font-size: 200%;
328
+ background-color: $lhasa_background_color;
329
+ }
330
+
331
+ .lhasa_dark_mode .pre_render_message{
332
+ color: $lhasa_text_color_dark;
333
+ }
334
+
335
+ .warning_box {
336
+ color: darkred;
337
+ background-color: color.adjust(darkorange, $alpha: -0.90);
338
+ border: red 1px solid;
339
+ border-radius: 3px;
340
+ padding: $lhasa_base_padding;
341
+ }
342
+
343
+ .lhasa_dark_mode .warning_box {
344
+ color: red;
345
+ // background-color: ;
346
+ }
347
+
348
+ .text_measurement_worker_div {
349
+ /* Cancels out the gap in the owning container
350
+ so that we get nice alignment */
351
+ margin-left: -$lhasa_base_padding;
352
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,79 @@
1
+ import React from 'react'
2
+ import { useState, useCallback, useEffect } from 'react'
3
+
4
+ import ReactDOM from 'react-dom/client'
5
+ import { LhasaComponent } from './Lhasa.tsx'
6
+ import './index.scss'
7
+ // Type definitions for TS linter, auto-generated by Embind
8
+ import { MainModule } from './types'
9
+ // import { Window } from './index';
10
+ import { FormControl, FormControlLabel, Switch } from '@mui/material'
11
+
12
+ // const lhasa_module : MainModule = await Module();
13
+
14
+
15
+
16
+
17
+
18
+ export function App() {
19
+ const [showLhasa, setShowLhasa] = useState(true);
20
+ const [darkMode, setDarkMode] = useState(false);
21
+ const [isLhasaAttached, setLhasaAttached] = useState(window.LhasaModule !== undefined);
22
+
23
+ const handleLhasaAttached = useCallback(() => {
24
+ if (window.LhasaModule !== undefined) {
25
+ setLhasaAttached(true);
26
+ } else {
27
+ console.warn("Lhasa module not available... Cannot start Lhasa.")
28
+ }
29
+ }, []);
30
+
31
+ useEffect(() => {
32
+ document.addEventListener('lhasaModuleAttached', handleLhasaAttached);
33
+ return () => {
34
+ document.removeEventListener('lhasaModuleAttached', handleLhasaAttached)
35
+ };
36
+ }, [handleLhasaAttached]);
37
+
38
+
39
+ let MaybeLhasaComponent = isLhasaAttached ?
40
+ <LhasaComponent
41
+ Lhasa={window.LhasaModule}
42
+ show_top_panel={true}
43
+ // show_footer={true}
44
+ icons_path_prefix='icons'
45
+ smiles_callback={(internal_id, id_from_prop, smiles) => console.log("ID=", internal_id," SMILES=", smiles, "Id-From-Prop", id_from_prop)}
46
+ // Works when using `npx vite server --port 5174`
47
+ // Inside `vite.config.js` there is a proxy setup to redirect this to an actual bansu instance.
48
+ // CORS stuff is broken for localhost connections, it seems.
49
+ // bansu_endpoint='http://localhost:5174'
50
+
51
+ bansu_endpoint='https://www.ccp4.ac.uk/bansu'
52
+ data_path_prefix=''
53
+ dark_mode={darkMode}
54
+ /> : <div>
55
+ Lhasa module not loaded yet
56
+ </div>;
57
+
58
+ return (
59
+ <>
60
+ <FormControl>
61
+ <FormControlLabel
62
+ control={<Switch checked={showLhasa} onChange={(event) => setShowLhasa(event.target.checked)} />}
63
+ label={"Show Lhasa"}
64
+ />
65
+ <FormControlLabel
66
+ control={<Switch checked={darkMode} onChange={(event) => setDarkMode(event.target.checked)} />}
67
+ label={"Dark Mode"}
68
+ />
69
+ </FormControl>
70
+ {showLhasa ? MaybeLhasaComponent : null}
71
+ </>
72
+ )
73
+ }
74
+
75
+ ReactDOM.createRoot(document.getElementById('root')!).render(
76
+ <React.StrictMode>
77
+ <App />
78
+ </React.StrictMode>,
79
+ )
@@ -0,0 +1,14 @@
1
+ import { LinearProgress } from '@mui/material';
2
+ class QedPropertyInfoboxProps {
3
+ property_name!: string;
4
+ display_value: string | number | undefined;
5
+ progressbar_value: number | undefined;
6
+ }
7
+
8
+ export function QedPropertyInfobox(props: QedPropertyInfoboxProps) {
9
+ return <span className="qed_property_field">
10
+ <span className="qed_property_label">{props.property_name}</span>
11
+ <span className="qed_property_value">{props.display_value}</span>
12
+ {props.progressbar_value && <LinearProgress variant="determinate" value={props.progressbar_value * 100} />}
13
+ </span>;
14
+ }