arcane-os 0.42.2 → 0.44.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.
- package/CHANGELOG.md +28 -0
- package/README.md +1 -1
- package/browser-runtime/ai/twin-cloud.mjs +234 -0
- package/docs/reference/ai/twin-cloud.md +124 -0
- package/docs/reference/runtime-components.md +63 -10
- package/docs/reference/runtime-modules.md +64 -0
- package/package.json +2 -2
- package/runtime/arcane/components/data-view.html +136 -51
- package/runtime/arcane/components/file-manager.html +214 -32
- package/runtime/arcane/components/markdown-editor.html +70 -0
- package/runtime/arcane/components/modal.html +8 -4
- package/runtime/arcane/modules/PrintView.js +625 -0
|
@@ -118,6 +118,7 @@
|
|
|
118
118
|
<textarea id="entryMarkdown" class="entry-markdown" part="input"></textarea>
|
|
119
119
|
<section class="actions" part="actions">
|
|
120
120
|
<span id="status" class="status" part="status" aria-live="polite"></span>
|
|
121
|
+
<button id="print" part="print-action" type="button">Print</button>
|
|
121
122
|
<button id="save" part="save-action" type="button" disabled></button>
|
|
122
123
|
</section>
|
|
123
124
|
</section>
|
|
@@ -143,6 +144,7 @@
|
|
|
143
144
|
const toolbar=host.shadowRoot.querySelector('#toolbar');
|
|
144
145
|
const textarea=host.shadowRoot.querySelector('#entryMarkdown');
|
|
145
146
|
const saveButton=host.shadowRoot.querySelector('#save');
|
|
147
|
+
const printButton=host.shadowRoot.querySelector('#print');
|
|
146
148
|
const status=host.shadowRoot.querySelector('#status');
|
|
147
149
|
|
|
148
150
|
let previewFrame=0;
|
|
@@ -152,6 +154,23 @@
|
|
|
152
154
|
let saveController=null;
|
|
153
155
|
let destroyed=false;
|
|
154
156
|
let options=normalizeMarkdownOptions(optionsFromDataset());
|
|
157
|
+
// Printing loads independently of editor readiness and owns no saved state.
|
|
158
|
+
const printViewPromise=import('../modules/PrintView.js').then(
|
|
159
|
+
function prepareEditorPrint({createPrintView}){
|
|
160
|
+
if(destroyed){
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
return createPrintView({
|
|
164
|
+
host,
|
|
165
|
+
content:renderedPrintContent,
|
|
166
|
+
title:()=>titleInput.value,
|
|
167
|
+
active:()=>!destroyed&&host.isConnected&&host.getClientRects().length>0,
|
|
168
|
+
signal:lifecycleController.signal,
|
|
169
|
+
onError:reportPrintFailure
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
void printViewPromise.catch(reportPrintFailure);
|
|
155
174
|
|
|
156
175
|
function emit(type,detail={},publicDetail={},operationId=null){
|
|
157
176
|
if(destroyed){
|
|
@@ -166,6 +185,8 @@
|
|
|
166
185
|
host.destroy=destroy;
|
|
167
186
|
host.focus=()=>{if(destroyed)return false;textarea.focus();return true;};
|
|
168
187
|
host.saveEntry=saveEntry;
|
|
188
|
+
host.print=print;
|
|
189
|
+
host.insertMarkdown=insertMarkdown;
|
|
169
190
|
|
|
170
191
|
Object.defineProperties(
|
|
171
192
|
host,
|
|
@@ -184,6 +205,7 @@
|
|
|
184
205
|
titleInput.addEventListener('input',contentChanged,{signal:lifecycleController.signal});
|
|
185
206
|
toolbar.addEventListener('click',formatMarkdown,{signal:lifecycleController.signal});
|
|
186
207
|
saveButton.addEventListener('click',saveEntry,{signal:lifecycleController.signal});
|
|
208
|
+
printButton.addEventListener('click',printFromControl,{signal:lifecycleController.signal});
|
|
187
209
|
for(const type of ['wheel','pointerdown','touchstart','keydown']){
|
|
188
210
|
preview.addEventListener(type,retainPreviewReadingPosition,{signal:lifecycleController.signal,passive:true});
|
|
189
211
|
}
|
|
@@ -488,6 +510,24 @@
|
|
|
488
510
|
contentChanged();
|
|
489
511
|
}
|
|
490
512
|
|
|
513
|
+
function insertMarkdown(markdown){
|
|
514
|
+
if(destroyed||options.readOnly){
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
if(!is.string(markdown)){
|
|
518
|
+
throw new TypeError('Markdown insertion requires a string.');
|
|
519
|
+
}
|
|
520
|
+
const sourceView=captureSourceView();
|
|
521
|
+
textarea.setRangeText(markdown,sourceView.selectionStart,sourceView.selectionEnd,'end');
|
|
522
|
+
sourceView.selectionStart+=markdown.length;
|
|
523
|
+
sourceView.selectionEnd=sourceView.selectionStart;
|
|
524
|
+
sourceView.selectionDirection='none';
|
|
525
|
+
textarea.focus({preventScroll:true});
|
|
526
|
+
restoreSourceView(sourceView);
|
|
527
|
+
contentChanged();
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
|
|
491
531
|
async function saveEntry(){
|
|
492
532
|
if(destroyed||options.readOnly||!options.showSave){
|
|
493
533
|
return false;
|
|
@@ -548,6 +588,36 @@
|
|
|
548
588
|
return resetEditor(true);
|
|
549
589
|
}
|
|
550
590
|
|
|
591
|
+
function renderedPrintContent(){
|
|
592
|
+
return preview;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
async function print(){
|
|
596
|
+
if(destroyed){
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
const printView=await printViewPromise;
|
|
600
|
+
if(destroyed||!printView){
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
if(previewFrame){
|
|
604
|
+
updatePreview(false);
|
|
605
|
+
}
|
|
606
|
+
return printView.print();
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function printFromControl(){
|
|
610
|
+
void print().catch(reportPrintFailure);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function reportPrintFailure(error){
|
|
614
|
+
if(destroyed||lifecycleController.signal.aborted){
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
arcaneLogging.error('Unable to print rendered Markdown:',error);
|
|
618
|
+
status.innerText='Unable to open print preview. Please try again.';
|
|
619
|
+
}
|
|
620
|
+
|
|
551
621
|
function resetEditor(supersede){
|
|
552
622
|
if(destroyed){
|
|
553
623
|
return false;
|
|
@@ -292,9 +292,13 @@
|
|
|
292
292
|
modalStack.push(host);
|
|
293
293
|
|
|
294
294
|
if(!wasOpen){
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
let focusedElement = document.activeElement;
|
|
296
|
+
while (focusedElement?.shadowRoot?.activeElement) {
|
|
297
|
+
focusedElement = focusedElement.shadowRoot.activeElement;
|
|
298
|
+
}
|
|
299
|
+
returnFocus = focusedElement instanceof HTMLElement
|
|
300
|
+
? focusedElement
|
|
301
|
+
: null;
|
|
298
302
|
dialog.showModal();
|
|
299
303
|
queueMicrotask(focusOpenedModal);
|
|
300
304
|
emit('modal-opened',{}, {opened:true});
|
|
@@ -326,7 +330,7 @@
|
|
|
326
330
|
const target=returnFocus;
|
|
327
331
|
returnFocus=null;
|
|
328
332
|
queueMicrotask(function restoreModalReturnFocus(){
|
|
329
|
-
if(target?.isConnected){
|
|
333
|
+
if(target?.isConnected && !dialog.open){
|
|
330
334
|
target.focus({preventScroll:true});
|
|
331
335
|
}
|
|
332
336
|
});
|