Fossil SCM

pikchrshow layout tweaks.

stephan 2022-06-06 20:13 pikchrshow-wasm
Commit 32526f32e7958466e650119816d5cb733cdefabe4caab9cc98df67ede6a8d3f9
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -12,10 +12,12 @@
1212
1313
This is the main entry point for the WASM rendition of fossil's
1414
/pikchrshow app. It sets up the various UI bits, loads a Worker for
1515
the pikchr process, and manages the communication between the UI and
1616
worker.
17
+
18
+ API dependencies: fossil.dom, fossil.storage
1719
*/
1820
(function(F/*fossil object*/){
1921
'use strict';
2022
2123
/* Recall that the 'self' symbol, except where locally
@@ -159,19 +161,19 @@
159161
/**
160162
The 'pikchrshow-ready' event is fired (with no payload) when the
161163
wasm module has finished loading. */
162164
PS.addMsgHandler('pikchrshow-ready', function(){
163165
PS.clearMsgHandlers('pikchrshow-ready');
164
- F.onPikchrshowLoaded();
166
+ F.page.onPikchrshowLoaded();
165167
});
166168
167169
/**
168170
Performs all app initialization which must wait until after the
169171
worker module is loaded. This function removes itself when it's
170172
called.
171173
*/
172
- F.onPikchrshowLoaded = function(){
174
+ F.page.onPikchrshowLoaded = function(){
173175
delete this.onPikchrshowLoaded;
174176
// Unhide all elements which start out hidden
175177
EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
176178
const taInput = E('#input');
177179
const btnClearIn = E('#btn-clear');
@@ -195,10 +197,67 @@
195197
};
196198
btnRender.addEventListener('click',function(ev){
197199
ev.preventDefault();
198200
renderCurrentText();
199201
},false);
202
+
203
+ 0 && (function(){
204
+ /* Set up split-view controls... This _almost_ works correctly,
205
+ just needs some tweaking to account for switching between
206
+ side-by-side and top-bottom views. */
207
+ // adapted from https://htmldom.dev/create-resizable-split-views/
208
+ const Split = {
209
+ e:{
210
+ left: E('.zone-wrapper.input'),
211
+ right: E('.zone-wrapper.output'),
212
+ handle: E('.splitter-handle'),
213
+ parent: E('#main-wrapper')
214
+ },
215
+ x: 0, y: 0,
216
+ widthLeft: 0,
217
+ heightLeft: 0
218
+ };
219
+ Split.mouseDownHandler = function(e){
220
+ this.x = e.clientX;
221
+ this.y = e.clientY;
222
+ const r = this.e.left.getBoundingClientRect();
223
+ this.widthLeft = r.width;
224
+ this.heightLeft = r.height;
225
+ document.addEventListener('mousemove', this.mouseMoveHandler);
226
+ document.addEventListener('mouseup', this.mouseUpHandler);
227
+ }.bind(Split);
228
+ Split.mouseMoveHandler = function(e){
229
+ const isHorizontal = this.e.parent.classList.contains('side-by-side');
230
+ const dx = e.clientX - this.x;
231
+ const dy = e.clientY - this.y;
232
+ if(isHorizontal){
233
+ const w = ((this.widthLeft + dx) * 100)
234
+ / this.e.parent.getBoundingClientRect().width;
235
+ this.e.left.style.width = w+'%';
236
+ }else{
237
+ const h = ((this.heightLeft + dy) * 100)
238
+ / this.e.parent.getBoundingClientRect().height;
239
+ this.e.left.style.height = h+'%';
240
+ }
241
+ document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';
242
+ this.e.left.style.userSelect = 'none';
243
+ this.e.left.style.pointerEvents = 'none';
244
+ this.e.right.style.userSelect = 'none';
245
+ this.e.right.style.pointerEvents = 'none';
246
+ }.bind(Split);
247
+ Split.mouseUpHandler = function(e){
248
+ this.e.handle.style.removeProperty('cursor');
249
+ document.body.style.removeProperty('cursor');
250
+ this.e.left.style.removeProperty('user-select');
251
+ this.e.left.style.removeProperty('pointer-events');
252
+ this.e.right.style.removeProperty('user-select');
253
+ this.e.right.style.removeProperty('pointer-events');
254
+ document.removeEventListener('mousemove', this.mouseMoveHandler);
255
+ document.removeEventListener('mouseup', this.mouseUpHandler);
256
+ }.bind(Split);
257
+ Split.e.handle.addEventListener('mousedown', Split.mouseDownHandler);
258
+ })();
200259
201260
/** To be called immediately before work is sent to the
202261
worker. Updates some UI elements. The 'working'/'end'
203262
event will apply the inverse, undoing the bits this
204263
function does. This impl is not in the 'working'/'start'
@@ -366,45 +425,10 @@
366425
legend.addEventListener('click', function(){
367426
fs.classList.toggle('collapsed');
368427
content.forEach((d)=>d.classList.toggle('hidden'));
369428
}, false);
370429
});
371
-
372
- /**
373
- Given a DOM element, this routine measures its "effective
374
- height", which is the bounding top/bottom range of this element
375
- and all of its children, recursively. For some DOM structure
376
- cases, a parent may have a reported height of 0 even though
377
- children have non-0 sizes.
378
-
379
- Returns 0 if !e or if the element really has no height.
380
- */
381
- const effectiveHeight = function f(e){
382
- if(!e) return 0;
383
- if(!f.measure){
384
- f.measure = function callee(e, depth){
385
- if(!e) return;
386
- const m = e.getBoundingClientRect();
387
- if(0===depth){
388
- callee.top = m.top;
389
- callee.bottom = m.bottom;
390
- }else{
391
- callee.top = m.top ? Math.min(callee.top, m.top) : callee.top;
392
- callee.bottom = Math.max(callee.bottom, m.bottom);
393
- }
394
- Array.prototype.forEach.call(e.children,(e)=>callee(e,depth+1));
395
- if(0===depth){
396
- //console.debug("measure() height:",e.className, callee.top, callee.bottom, (callee.bottom - callee.top));
397
- f.extra += callee.bottom - callee.top;
398
- }
399
- return f.extra;
400
- };
401
- }
402
- f.extra = 0;
403
- f.measure(e,0);
404
- return f.extra;
405
- };
406430
407431
btnRender.click();
408432
409433
/** Debounce handler for auto-rendering while typing. */
410434
const debounceAutoRender = F.debounce(function f(){
@@ -462,11 +486,11 @@
462486
const resized = function f(){
463487
if(f.$disabled) return;
464488
const wh = window.innerHeight;
465489
var ht;
466490
var extra = 0;
467
- elemsToCount.forEach((e)=>e ? extra += effectiveHeight(e) : false);
491
+ elemsToCount.forEach((e)=>e ? extra += F.dom.effectiveHeight(e) : false);
468492
ht = wh - extra;
469493
appViews.forEach(function(e){
470494
e.style.height =
471495
e.style.maxHeight = [
472496
"calc(", (ht>=100 ? ht : 100), "px",
473497
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -12,10 +12,12 @@
12
13 This is the main entry point for the WASM rendition of fossil's
14 /pikchrshow app. It sets up the various UI bits, loads a Worker for
15 the pikchr process, and manages the communication between the UI and
16 worker.
 
 
17 */
18 (function(F/*fossil object*/){
19 'use strict';
20
21 /* Recall that the 'self' symbol, except where locally
@@ -159,19 +161,19 @@
159 /**
160 The 'pikchrshow-ready' event is fired (with no payload) when the
161 wasm module has finished loading. */
162 PS.addMsgHandler('pikchrshow-ready', function(){
163 PS.clearMsgHandlers('pikchrshow-ready');
164 F.onPikchrshowLoaded();
165 });
166
167 /**
168 Performs all app initialization which must wait until after the
169 worker module is loaded. This function removes itself when it's
170 called.
171 */
172 F.onPikchrshowLoaded = function(){
173 delete this.onPikchrshowLoaded;
174 // Unhide all elements which start out hidden
175 EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
176 const taInput = E('#input');
177 const btnClearIn = E('#btn-clear');
@@ -195,10 +197,67 @@
195 };
196 btnRender.addEventListener('click',function(ev){
197 ev.preventDefault();
198 renderCurrentText();
199 },false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
201 /** To be called immediately before work is sent to the
202 worker. Updates some UI elements. The 'working'/'end'
203 event will apply the inverse, undoing the bits this
204 function does. This impl is not in the 'working'/'start'
@@ -366,45 +425,10 @@
366 legend.addEventListener('click', function(){
367 fs.classList.toggle('collapsed');
368 content.forEach((d)=>d.classList.toggle('hidden'));
369 }, false);
370 });
371
372 /**
373 Given a DOM element, this routine measures its "effective
374 height", which is the bounding top/bottom range of this element
375 and all of its children, recursively. For some DOM structure
376 cases, a parent may have a reported height of 0 even though
377 children have non-0 sizes.
378
379 Returns 0 if !e or if the element really has no height.
380 */
381 const effectiveHeight = function f(e){
382 if(!e) return 0;
383 if(!f.measure){
384 f.measure = function callee(e, depth){
385 if(!e) return;
386 const m = e.getBoundingClientRect();
387 if(0===depth){
388 callee.top = m.top;
389 callee.bottom = m.bottom;
390 }else{
391 callee.top = m.top ? Math.min(callee.top, m.top) : callee.top;
392 callee.bottom = Math.max(callee.bottom, m.bottom);
393 }
394 Array.prototype.forEach.call(e.children,(e)=>callee(e,depth+1));
395 if(0===depth){
396 //console.debug("measure() height:",e.className, callee.top, callee.bottom, (callee.bottom - callee.top));
397 f.extra += callee.bottom - callee.top;
398 }
399 return f.extra;
400 };
401 }
402 f.extra = 0;
403 f.measure(e,0);
404 return f.extra;
405 };
406
407 btnRender.click();
408
409 /** Debounce handler for auto-rendering while typing. */
410 const debounceAutoRender = F.debounce(function f(){
@@ -462,11 +486,11 @@
462 const resized = function f(){
463 if(f.$disabled) return;
464 const wh = window.innerHeight;
465 var ht;
466 var extra = 0;
467 elemsToCount.forEach((e)=>e ? extra += effectiveHeight(e) : false);
468 ht = wh - extra;
469 appViews.forEach(function(e){
470 e.style.height =
471 e.style.maxHeight = [
472 "calc(", (ht>=100 ? ht : 100), "px",
473
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -12,10 +12,12 @@
12
13 This is the main entry point for the WASM rendition of fossil's
14 /pikchrshow app. It sets up the various UI bits, loads a Worker for
15 the pikchr process, and manages the communication between the UI and
16 worker.
17
18 API dependencies: fossil.dom, fossil.storage
19 */
20 (function(F/*fossil object*/){
21 'use strict';
22
23 /* Recall that the 'self' symbol, except where locally
@@ -159,19 +161,19 @@
161 /**
162 The 'pikchrshow-ready' event is fired (with no payload) when the
163 wasm module has finished loading. */
164 PS.addMsgHandler('pikchrshow-ready', function(){
165 PS.clearMsgHandlers('pikchrshow-ready');
166 F.page.onPikchrshowLoaded();
167 });
168
169 /**
170 Performs all app initialization which must wait until after the
171 worker module is loaded. This function removes itself when it's
172 called.
173 */
174 F.page.onPikchrshowLoaded = function(){
175 delete this.onPikchrshowLoaded;
176 // Unhide all elements which start out hidden
177 EAll('.initially-hidden').forEach((e)=>e.classList.remove('initially-hidden'));
178 const taInput = E('#input');
179 const btnClearIn = E('#btn-clear');
@@ -195,10 +197,67 @@
197 };
198 btnRender.addEventListener('click',function(ev){
199 ev.preventDefault();
200 renderCurrentText();
201 },false);
202
203 0 && (function(){
204 /* Set up split-view controls... This _almost_ works correctly,
205 just needs some tweaking to account for switching between
206 side-by-side and top-bottom views. */
207 // adapted from https://htmldom.dev/create-resizable-split-views/
208 const Split = {
209 e:{
210 left: E('.zone-wrapper.input'),
211 right: E('.zone-wrapper.output'),
212 handle: E('.splitter-handle'),
213 parent: E('#main-wrapper')
214 },
215 x: 0, y: 0,
216 widthLeft: 0,
217 heightLeft: 0
218 };
219 Split.mouseDownHandler = function(e){
220 this.x = e.clientX;
221 this.y = e.clientY;
222 const r = this.e.left.getBoundingClientRect();
223 this.widthLeft = r.width;
224 this.heightLeft = r.height;
225 document.addEventListener('mousemove', this.mouseMoveHandler);
226 document.addEventListener('mouseup', this.mouseUpHandler);
227 }.bind(Split);
228 Split.mouseMoveHandler = function(e){
229 const isHorizontal = this.e.parent.classList.contains('side-by-side');
230 const dx = e.clientX - this.x;
231 const dy = e.clientY - this.y;
232 if(isHorizontal){
233 const w = ((this.widthLeft + dx) * 100)
234 / this.e.parent.getBoundingClientRect().width;
235 this.e.left.style.width = w+'%';
236 }else{
237 const h = ((this.heightLeft + dy) * 100)
238 / this.e.parent.getBoundingClientRect().height;
239 this.e.left.style.height = h+'%';
240 }
241 document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';
242 this.e.left.style.userSelect = 'none';
243 this.e.left.style.pointerEvents = 'none';
244 this.e.right.style.userSelect = 'none';
245 this.e.right.style.pointerEvents = 'none';
246 }.bind(Split);
247 Split.mouseUpHandler = function(e){
248 this.e.handle.style.removeProperty('cursor');
249 document.body.style.removeProperty('cursor');
250 this.e.left.style.removeProperty('user-select');
251 this.e.left.style.removeProperty('pointer-events');
252 this.e.right.style.removeProperty('user-select');
253 this.e.right.style.removeProperty('pointer-events');
254 document.removeEventListener('mousemove', this.mouseMoveHandler);
255 document.removeEventListener('mouseup', this.mouseUpHandler);
256 }.bind(Split);
257 Split.e.handle.addEventListener('mousedown', Split.mouseDownHandler);
258 })();
259
260 /** To be called immediately before work is sent to the
261 worker. Updates some UI elements. The 'working'/'end'
262 event will apply the inverse, undoing the bits this
263 function does. This impl is not in the 'working'/'start'
@@ -366,45 +425,10 @@
425 legend.addEventListener('click', function(){
426 fs.classList.toggle('collapsed');
427 content.forEach((d)=>d.classList.toggle('hidden'));
428 }, false);
429 });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
431 btnRender.click();
432
433 /** Debounce handler for auto-rendering while typing. */
434 const debounceAutoRender = F.debounce(function f(){
@@ -462,11 +486,11 @@
486 const resized = function f(){
487 if(f.$disabled) return;
488 const wh = window.innerHeight;
489 var ht;
490 var extra = 0;
491 elemsToCount.forEach((e)=>e ? extra += F.dom.effectiveHeight(e) : false);
492 ht = wh - extra;
493 appViews.forEach(function(e){
494 e.style.height =
495 e.style.maxHeight = [
496 "calc(", (ht>=100 ? ht : 100), "px",
497
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -481,10 +481,11 @@
481481
CX("<div class='button-bar'>");
482482
CX("<button id='btn-render'>Render</button>");
483483
CX("<button id='btn-clear'>Clear Input</button>");
484484
CX("</div><!-- .button-bar -->");
485485
} CX("</div><!-- .zone-wrapper.input -->");
486
+ CX("<div class='splitter-handle hidden'></div>");
486487
CX("<div class='zone-wrapper output'>"); {
487488
CX("<div id='pikchr-output-wrapper'>");
488489
CX("<div id='pikchr-output'></div>");
489490
CX("</div>");
490491
CX("<div class='button-bar'>");
@@ -491,11 +492,11 @@
491492
CX("<button id='btn-render-mode'>Toggle Render Mode</button>");
492493
CX("</div><!-- .button-bar -->");
493494
} CX("</div> <!-- .zone-wrapper.output -->");
494495
} CX("</div><!-- #main-wrapper -->");
495496
} CX("</div><!-- #view-split -->");
496
- builtin_fossil_js_bundle_or("storage", NULL);
497
+ builtin_fossil_js_bundle_or("dom", "storage", NULL);
497498
builtin_request_js("fossil.page.pikchrshowasm.js");
498499
builtin_fulfill_js_requests();
499500
style_finish_page();
500501
}
501502
502503
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -481,10 +481,11 @@
481 CX("<div class='button-bar'>");
482 CX("<button id='btn-render'>Render</button>");
483 CX("<button id='btn-clear'>Clear Input</button>");
484 CX("</div><!-- .button-bar -->");
485 } CX("</div><!-- .zone-wrapper.input -->");
 
486 CX("<div class='zone-wrapper output'>"); {
487 CX("<div id='pikchr-output-wrapper'>");
488 CX("<div id='pikchr-output'></div>");
489 CX("</div>");
490 CX("<div class='button-bar'>");
@@ -491,11 +492,11 @@
491 CX("<button id='btn-render-mode'>Toggle Render Mode</button>");
492 CX("</div><!-- .button-bar -->");
493 } CX("</div> <!-- .zone-wrapper.output -->");
494 } CX("</div><!-- #main-wrapper -->");
495 } CX("</div><!-- #view-split -->");
496 builtin_fossil_js_bundle_or("storage", NULL);
497 builtin_request_js("fossil.page.pikchrshowasm.js");
498 builtin_fulfill_js_requests();
499 style_finish_page();
500 }
501
502
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -481,10 +481,11 @@
481 CX("<div class='button-bar'>");
482 CX("<button id='btn-render'>Render</button>");
483 CX("<button id='btn-clear'>Clear Input</button>");
484 CX("</div><!-- .button-bar -->");
485 } CX("</div><!-- .zone-wrapper.input -->");
486 CX("<div class='splitter-handle hidden'></div>");
487 CX("<div class='zone-wrapper output'>"); {
488 CX("<div id='pikchr-output-wrapper'>");
489 CX("<div id='pikchr-output'></div>");
490 CX("</div>");
491 CX("<div class='button-bar'>");
@@ -491,11 +492,11 @@
492 CX("<button id='btn-render-mode'>Toggle Render Mode</button>");
493 CX("</div><!-- .button-bar -->");
494 } CX("</div> <!-- .zone-wrapper.output -->");
495 } CX("</div><!-- #main-wrapper -->");
496 } CX("</div><!-- #view-split -->");
497 builtin_fossil_js_bundle_or("dom", "storage", NULL);
498 builtin_request_js("fossil.page.pikchrshowasm.js");
499 builtin_fulfill_js_requests();
500 style_finish_page();
501 }
502
503
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -23,19 +23,22 @@
2323
from {transform: rotate(0deg);}
2424
to {transform: rotate(360deg);}
2525
}
2626
2727
/* The following styles are for app-level use. */
28
+/* TODO: consolidate the WASM- and legacy-mode CSS into this file.
29
+ Since they share a URI, they both load this file. */
2830
textarea {
2931
font-family: monospace;
3032
flex: 1 1 auto;
3133
}
3234
#main-wrapper {
3335
display: flex;
3436
flex-direction: column-reverse;
3537
flex: 1 1 auto;
3638
margin: 0.5em 0;
39
+ overflow: hidden;
3740
}
3841
#main-wrapper.side-by-side {
3942
flex-direction: row-reverse;
4043
}
4144
#main-wrapper.swapio {
@@ -42,27 +45,37 @@
4245
flex-direction: column;
4346
}
4447
#main-wrapper.side-by-side.swapio {
4548
flex-direction: row;
4649
}
50
+#main-wrapper .splitter-handle {
51
+ border: 1px outset;
52
+ border-radius: 0.25em;
53
+}
54
+#main-wrapper.side-by-side .splitter-handle {
55
+ width: 2px;
56
+}
57
+#main-wrapper:not(.side-by-side) .splitter-handle {
58
+ width: 100%;
59
+ height: 2px;
60
+}
4761
.zone-wrapper{
4862
display: flex;
4963
flex-direction: column;
5064
align-items: stretch;
5165
margin: 0 0.25em;
52
- flex: 1 1 auto;
66
+ flex: 1 1 0%;
5367
}
5468
.zone-wrapper.output {
69
+ /*flex: 1 1 0%;*/
5570
}
56
-#main-wrapper.auto-render.side-by-side .zone-wrapper {
71
+#main-wrapper.side-by-side .zone-wrapper {
5772
/* Keep the layout from "flopping around" when
5873
render-while-typing mode is on. */
59
- max-width: 50%;
74
+ /*max-width: 50%;*/
6075
}
6176
#pikchr-output {
62
- /*flex: 1 1 auto;*/
63
- /*overflow: auto;*/
6477
padding: 0;
6578
margin: 0;
6679
}
6780
#pikchr-output-wrapper {
6881
flex: 1 1 auto;
@@ -83,10 +96,11 @@
8396
.zone-wrapper textarea {
8497
flex: 10 1 auto;
8598
}
8699
.zone-wrapper.input {
87100
/*min-height: 10em;*/
101
+ /*width: 50%;*/
88102
min-width: 20em;
89103
}
90104
.zone-wrapper.output {
91105
overflow: auto;
92106
justify-content: space-between;
@@ -133,11 +147,11 @@
133147
cursor: pointer;
134148
}
135149
.fieldset.options > div {
136150
display: flex;
137151
flex-wrap: wrap;
138
- font-size: 70%;
152
+ font-size: 85%;
139153
margin: 0 0.5em 0.5em 0.5em;
140154
}
141155
.fieldset > .legend > span {
142156
position: relative;
143157
}
@@ -166,10 +180,13 @@
166180
border-radius: 0.25em;
167181
white-space: nowrap;
168182
background: #0002;
169183
display: flex;
170184
align-items: center;
185
+}
186
+span.labeled-input > *:nth-child(2) {
187
+ margin-left: 0.5em;
171188
}
172189
.center { text-align: center; }
173190
.app-view {
174191
flex: 20 1 auto;
175192
}
176193
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -23,19 +23,22 @@
23 from {transform: rotate(0deg);}
24 to {transform: rotate(360deg);}
25 }
26
27 /* The following styles are for app-level use. */
 
 
28 textarea {
29 font-family: monospace;
30 flex: 1 1 auto;
31 }
32 #main-wrapper {
33 display: flex;
34 flex-direction: column-reverse;
35 flex: 1 1 auto;
36 margin: 0.5em 0;
 
37 }
38 #main-wrapper.side-by-side {
39 flex-direction: row-reverse;
40 }
41 #main-wrapper.swapio {
@@ -42,27 +45,37 @@
42 flex-direction: column;
43 }
44 #main-wrapper.side-by-side.swapio {
45 flex-direction: row;
46 }
 
 
 
 
 
 
 
 
 
 
 
47 .zone-wrapper{
48 display: flex;
49 flex-direction: column;
50 align-items: stretch;
51 margin: 0 0.25em;
52 flex: 1 1 auto;
53 }
54 .zone-wrapper.output {
 
55 }
56 #main-wrapper.auto-render.side-by-side .zone-wrapper {
57 /* Keep the layout from "flopping around" when
58 render-while-typing mode is on. */
59 max-width: 50%;
60 }
61 #pikchr-output {
62 /*flex: 1 1 auto;*/
63 /*overflow: auto;*/
64 padding: 0;
65 margin: 0;
66 }
67 #pikchr-output-wrapper {
68 flex: 1 1 auto;
@@ -83,10 +96,11 @@
83 .zone-wrapper textarea {
84 flex: 10 1 auto;
85 }
86 .zone-wrapper.input {
87 /*min-height: 10em;*/
 
88 min-width: 20em;
89 }
90 .zone-wrapper.output {
91 overflow: auto;
92 justify-content: space-between;
@@ -133,11 +147,11 @@
133 cursor: pointer;
134 }
135 .fieldset.options > div {
136 display: flex;
137 flex-wrap: wrap;
138 font-size: 70%;
139 margin: 0 0.5em 0.5em 0.5em;
140 }
141 .fieldset > .legend > span {
142 position: relative;
143 }
@@ -166,10 +180,13 @@
166 border-radius: 0.25em;
167 white-space: nowrap;
168 background: #0002;
169 display: flex;
170 align-items: center;
 
 
 
171 }
172 .center { text-align: center; }
173 .app-view {
174 flex: 20 1 auto;
175 }
176
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -23,19 +23,22 @@
23 from {transform: rotate(0deg);}
24 to {transform: rotate(360deg);}
25 }
26
27 /* The following styles are for app-level use. */
28 /* TODO: consolidate the WASM- and legacy-mode CSS into this file.
29 Since they share a URI, they both load this file. */
30 textarea {
31 font-family: monospace;
32 flex: 1 1 auto;
33 }
34 #main-wrapper {
35 display: flex;
36 flex-direction: column-reverse;
37 flex: 1 1 auto;
38 margin: 0.5em 0;
39 overflow: hidden;
40 }
41 #main-wrapper.side-by-side {
42 flex-direction: row-reverse;
43 }
44 #main-wrapper.swapio {
@@ -42,27 +45,37 @@
45 flex-direction: column;
46 }
47 #main-wrapper.side-by-side.swapio {
48 flex-direction: row;
49 }
50 #main-wrapper .splitter-handle {
51 border: 1px outset;
52 border-radius: 0.25em;
53 }
54 #main-wrapper.side-by-side .splitter-handle {
55 width: 2px;
56 }
57 #main-wrapper:not(.side-by-side) .splitter-handle {
58 width: 100%;
59 height: 2px;
60 }
61 .zone-wrapper{
62 display: flex;
63 flex-direction: column;
64 align-items: stretch;
65 margin: 0 0.25em;
66 flex: 1 1 0%;
67 }
68 .zone-wrapper.output {
69 /*flex: 1 1 0%;*/
70 }
71 #main-wrapper.side-by-side .zone-wrapper {
72 /* Keep the layout from "flopping around" when
73 render-while-typing mode is on. */
74 /*max-width: 50%;*/
75 }
76 #pikchr-output {
 
 
77 padding: 0;
78 margin: 0;
79 }
80 #pikchr-output-wrapper {
81 flex: 1 1 auto;
@@ -83,10 +96,11 @@
96 .zone-wrapper textarea {
97 flex: 10 1 auto;
98 }
99 .zone-wrapper.input {
100 /*min-height: 10em;*/
101 /*width: 50%;*/
102 min-width: 20em;
103 }
104 .zone-wrapper.output {
105 overflow: auto;
106 justify-content: space-between;
@@ -133,11 +147,11 @@
147 cursor: pointer;
148 }
149 .fieldset.options > div {
150 display: flex;
151 flex-wrap: wrap;
152 font-size: 85%;
153 margin: 0 0.5em 0.5em 0.5em;
154 }
155 .fieldset > .legend > span {
156 position: relative;
157 }
@@ -166,10 +180,13 @@
180 border-radius: 0.25em;
181 white-space: nowrap;
182 background: #0002;
183 display: flex;
184 align-items: center;
185 }
186 span.labeled-input > *:nth-child(2) {
187 margin-left: 0.5em;
188 }
189 .center { text-align: center; }
190 .app-view {
191 flex: 20 1 auto;
192 }
193

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button