arcane-os 0.42.2 → 0.43.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 +14 -0
- package/README.md +1 -1
- package/docs/reference/runtime-components.md +63 -10
- package/docs/reference/runtime-modules.md +64 -0
- package/package.json +1 -1
- 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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.43.0
|
|
4
|
+
|
|
5
|
+
- Add reusable rendered printing through `createPrintView`, preserving the
|
|
6
|
+
complete rendered content, title, styles and prepared image/font resources.
|
|
7
|
+
Explicit print requests await preparation; native printing uses the active
|
|
8
|
+
view. Resources remain owned through `afterprint`.
|
|
9
|
+
- Add Markdown editor `print()` and `insertMarkdown(text)` and file-manager
|
|
10
|
+
`printPreview()`. Insertion replaces the current selection through the
|
|
11
|
+
ordinary full-content change lifecycle; printing does not save the document.
|
|
12
|
+
- Add reusable history/file-manager `close()` with child-first closure and
|
|
13
|
+
pending-open cancellation. Refused or failed closure preserves the settled
|
|
14
|
+
visible preview, media and printing until its dialog actually closes.
|
|
15
|
+
Preserve modal focus restoration and existing saved records without migration.
|
|
16
|
+
|
|
3
17
|
## 0.42.2
|
|
4
18
|
|
|
5
19
|
- Stop generating SDK cache suffixes in import maps, materialized runtime,
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
|
|
|
19
19
|
`arcane/` runtime. Both profiles share the theme, packaging, event, cancellation,
|
|
20
20
|
and browser run contracts while retaining their selected application layout.
|
|
21
21
|
|
|
22
|
-
This checkout defines the `0.
|
|
22
|
+
This checkout defines the `0.43.0` SDK contract. Applications pin one exact npm
|
|
23
23
|
version and lockfile; registry state is deliberately not baked into application
|
|
24
24
|
artifacts.
|
|
25
25
|
|
|
@@ -67,17 +67,17 @@ appropriate.
|
|
|
67
67
|
| [`conversation-view.html`](#conversation-viewhtml) | Provider-neutral conversation display, advisory actions, composer, busy state, and status. | `setConversation()`<br>`setBusy()`<br>`setStatus()`<br>`clearComposer()`<br>`destroy()` | `conversation-view-ready`<br>`communication-send`<br>`communication-advisory-action` | DOM-normalized |
|
|
68
68
|
| [`dashboard-config.html`](#dashboard-confightml) | Selects which normalized chart definitions are visible on a dashboard. | `configure()`<br>`setDefinitions()`<br>`setVisibility()`<br>`getChartOptions()`<br>`getEffectiveVisibility()`<br>`open()`<br>`close()`<br>`destroy()` | `dashboard-config-ready`<br>`dashboard-config-opened`<br>`dashboard-config-closed`<br>`dashboard-config-change` | Fully normalized definitions and visibility |
|
|
69
69
|
| [`data-maintenance.html`](#data-maintenancehtml) | Runs destructive cleanup of empty chats and memories inside the current app data scope. | `open()`<br>`destroy()` | `data-maintenance-ready`<br>`data-maintenance-complete` | Normalized counts; DBOPFS failures mixed |
|
|
70
|
-
| [`data-view.html`](#data-viewhtml) | Opens a modal file view and forwards application-owned preview and directory-filter callbacks. | `beforeOpen()`<br>`open()`<br>`destroy()` | `data-view-ready` | DOM-native result; preview/filter configuration reaches the child before loading |
|
|
70
|
+
| [`data-view.html`](#data-viewhtml) | Opens a modal file view and forwards application-owned preview and directory-filter callbacks. | `beforeOpen()`<br>`open()`<br>`close()`<br>`printPreview()`<br>`destroy()` | `data-view-ready` | DOM-native result; preview/filter configuration reaches the child before loading |
|
|
71
71
|
| [`directory-picker.html`](#directory-pickerhtml) | Presents the provider-owned OS directory chooser with change/cancel/error states. | `configure()`<br>`focus()`<br>`select()`<br>`destroy()` | `directory-picker-ready`<br>`directory-picker-change`<br>`directory-picker-cancel`<br>`directory-picker-error` | Complete plain-text paths and native selection/error |
|
|
72
72
|
| [`document-inspector.html`](#document-inspectorhtml) | Inspects PDF, text, or source documents and records review state. | `loadDocument()`<br>`selectView()`<br>`markSaved()`<br>`destroy()` | `document-inspector-ready`<br>`document-review-change` | Document state normalized; browser document APIs mixed |
|
|
73
73
|
| [`file-drop.html`](#file-drophtml) | Acquires complete file selections by drag/drop or picker and presents busy, progress, error, and cleared state. | `configure()`<br>`openPicker()`<br>`clear()`<br>`setBusy()`<br>`setError()`<br>`setProgress()`<br>`destroy()` | `file-drop-ready`<br>`file-drop-selected`<br>`file-drop-progress`<br>`file-drop-state`<br>`file-drop-error` | Complete selections preserved; browser File/drop errors mixed |
|
|
74
74
|
| [`file-inspector.html`](#file-inspectorhtml) | Displays file metadata, preview, busy/error state, and caller-defined actions. | `configure()`<br>`show()`<br>`clear()`<br>`setActions()`<br>`setBusy()`<br>`setError()`<br>`setPreview()`<br>`destroy()` | `file-inspector-ready`<br>`file-inspector-action`<br>`file-inspector-change`<br>`file-inspector-cleared`<br>`file-inspector-error` | State normalized; preview/provider behavior mixed |
|
|
75
|
-
| [`file-manager.html`](#file-managerhtml) | Browses app-scoped files, filters directories before reads, and renders application-described previews. | `setProvider()`<br>`loadAll()`<br>`setFilter()`<br>`setDirectoryFilter()`<br>`select()`<br>`clearSelection()`<br>`destroy()` | `file-manager-ready`<br>`file-manager-select`<br>`file-manager-open`<br>`file-manager-action` | Selection/filter state, neutral preview descriptors, cancellation, and media cleanup normalized; storage/provider behavior mixed |
|
|
75
|
+
| [`file-manager.html`](#file-managerhtml) | Browses app-scoped files, filters directories before reads, and renders application-described previews. | `setProvider()`<br>`loadAll()`<br>`setFilter()`<br>`setDirectoryFilter()`<br>`select()`<br>`clearSelection()`<br>`close()`<br>`printPreview()`<br>`destroy()` | `file-manager-ready`<br>`file-manager-select`<br>`file-manager-open`<br>`file-manager-action` | Selection/filter state, neutral preview descriptors, cancellation, and media cleanup normalized; storage/provider behavior mixed |
|
|
76
76
|
| [`header.html`](#headerhtml) | Shared title bar with history, reload, online marker, presentation labels, and 988 link. | None | No component-specific event | Browser/platform-native behavior; no component-ready contract |
|
|
77
77
|
| [`integration-settings.html`](#integration-settingshtml) | Edits non-secret communication service configuration and service actions. | `configure()`<br>`getValues()`<br>`setStatus()`<br>`destroy()` | `integration-settings-ready`<br>`integration-settings-save`<br>`integration-settings-close`<br>`integration-action` | Normalized non-secret values |
|
|
78
78
|
| [`local-ai-status.html`](#local-ai-statushtml) | Presents local-AI standby, failure, recovery, guidance, retry, and dismissal states. | `configure()`<br>`begin()`<br>`present()`<br>`destroy()`<br>`hidden` | `local-ai-status-ready`<br>`local-ai-status-dismissed`<br>`local-ai-retry` | Fully normalized LocalAIReadiness report |
|
|
79
79
|
| [`markdown-document.html`](#markdown-documenthtml) | Renders and navigates a complete Markdown document with focusable fragments. | `configure()`<br>`load()`<br>`render()`<br>`clear()`<br>`fail()`<br>`focus()`<br>`focusFragment()`<br>`destroy()` | `markdown-document-ready`<br>`markdown-document-state`<br>`markdown-document-loading`<br>`markdown-document-rendered`<br>`markdown-document-empty`<br>`markdown-document-error`<br>`markdown-document-navigate` | Complete Markdown/state normalized; malformed input and Marked/DOM failures remain visible |
|
|
80
|
-
| [`markdown-editor.html`](#markdown-editorhtml) | Configurable Markdown authoring with optional bounded input/preview panes
|
|
80
|
+
| [`markdown-editor.html`](#markdown-editorhtml) | Configurable Markdown authoring with optional bounded input/preview panes, edit-position following, and rendered printing. | `configure()`<br>`focus()`<br>`clear()`<br>`insertMarkdown()`<br>`saveEntry()`<br>`print()`<br>`destroy()` | `markdown-editor-ready`<br>`markdown-editor-change`<br>`markdown-editor-saved` | Editor values, opt-in fit layout, and preview following normalized; injected save result mixed |
|
|
81
81
|
| [`media-embed.html`](#media-embedhtml) | Loads a parsed YouTube video or playlist embed with ordinary hosting by default, optional privacy enhancement, and an external-platform action. | `configure()`<br>`load()`<br>`destroy()` | `media-embed-ready`<br>`media-load`<br>`media-error`<br>`media-open-platform` | URL/error normalized; iframe/platform behavior native |
|
|
82
82
|
| [`modal.html`](#modalhtml) | Generic modal with population, configurable user dismissal, actions, and concurrent task execution. | `configure()`<br>`populate()`<br>`open()`<br>`close()`<br>`runTasks()`<br>`destroy()`<br>`running`<br>`opened` | `modal-ready`<br>`modal-opened`<br>`modal-closed`<br>`modal-action` | Modal state normalized; injected task results mixed |
|
|
83
83
|
| [`output-panel.html`](#output-panelhtml) | Presents status, output, body, coverage, actions, pending, error, and cleared states. | `configure()`<br>`setOutput()`<br>`setBody()`<br>`setCoverage()`<br>`setActions()`<br>`setPending()`<br>`setStatus()`<br>`setError()`<br>`clear()`<br>`destroy()` | `output-panel-ready`<br>`output-panel-state`<br>`output-panel-change`<br>`output-panel-action`<br>`output-panel-error`<br>`output-panel-cleared` | DOM-normalized |
|
|
@@ -663,7 +663,7 @@ own record mappings through the same preview callbacks as the standalone
|
|
|
663
663
|
|
|
664
664
|
### Public surface
|
|
665
665
|
|
|
666
|
-
Methods/properties: `beforeOpen()`, `open()`, `destroy()`.
|
|
666
|
+
Methods/properties: `beforeOpen()`, `open()`, `close()`, `printPreview()`, `destroy()`.
|
|
667
667
|
|
|
668
668
|
Assign `previewDescriptor`, `previewTransform`, and `directoryFilter` on the
|
|
669
669
|
host before opening. The component forwards those callbacks, comma-separated
|
|
@@ -673,6 +673,20 @@ before the child's first load. Reopening refreshes those values before
|
|
|
673
673
|
`beforeOpen()` is awaited before this configuration is consumed. `data-dirs`
|
|
674
674
|
selects the initial directories; `data-layout` defaults to `files`.
|
|
675
675
|
|
|
676
|
+
`await close()` invalidates pending opens, closes the child's dialogs before the
|
|
677
|
+
parent, and returns `true` only after closure. It returns `false` when destroyed
|
|
678
|
+
or a child/parent cannot close; complete errors reach shared diagnostics. It is
|
|
679
|
+
reusable: a later `open()` reloads the existing child. Repeated closes share the
|
|
680
|
+
pending closure. `destroy()` remains terminal.
|
|
681
|
+
|
|
682
|
+
An application that loads a history selection into an editor must synchronously
|
|
683
|
+
call `preventDefault()` on the existing cancelable `file-manager-open` event
|
|
684
|
+
before awaiting its own save/load work. That application owns record selection,
|
|
685
|
+
autosave, title, and editor focus; call `close()` after loading and restore focus
|
|
686
|
+
after it resolves `true`. No record-loading policy is added to the SDK.
|
|
687
|
+
`printPreview()` forwards to the currently open child preview and returns
|
|
688
|
+
`false` when no such preview is available.
|
|
689
|
+
|
|
676
690
|
Events: `data-view-ready`.
|
|
677
691
|
|
|
678
692
|
Shared dependencies: [`WaitForComponent.js`](runtime-modules.md#waitforcomponentjs).
|
|
@@ -821,7 +835,7 @@ and `destroy()` cleanup, without delaying unrelated component startup.
|
|
|
821
835
|
### Public surface
|
|
822
836
|
|
|
823
837
|
Methods/properties: `setProvider()`, `loadAll()`, `setFilter()`,
|
|
824
|
-
`setDirectoryFilter()`, `select()`, `clearSelection()`, `destroy()`,
|
|
838
|
+
`setDirectoryFilter()`, `select()`, `clearSelection()`, `close()`, `printPreview()`, `destroy()`,
|
|
825
839
|
`previewDescriptor`, `previewTransform`, `directoryFilter`.
|
|
826
840
|
|
|
827
841
|
Assign `directoryFilter(entry, context)` before the first load, or call
|
|
@@ -879,8 +893,9 @@ component does not automatically read every related media variant.
|
|
|
879
893
|
|
|
880
894
|
Closing the preview, opening another file, or destroying the manager aborts
|
|
881
895
|
the preview signal, ignores late descriptor/loader results, stops owned audio,
|
|
882
|
-
removes iframe `srcdoc`, and
|
|
883
|
-
|
|
896
|
+
removes iframe `srcdoc`, and releases owned object URLs, including those in
|
|
897
|
+
nested collections. An active print snapshot retains its URLs until the
|
|
898
|
+
browser's `afterprint` event, even when the preview closes meanwhile.
|
|
884
899
|
Applications should observe the supplied signal in their asynchronous reads.
|
|
885
900
|
Descriptor and file-open failures show `Unable to open this file.` in the
|
|
886
901
|
current modal and send the original error to the shared logger.
|
|
@@ -900,6 +915,26 @@ of the original `File`.
|
|
|
900
915
|
The larger file-preview dialog reuses `--modal-width`, `--modal-max-height`,
|
|
901
916
|
and `--modal-padding`; applications can override those existing modal values.
|
|
902
917
|
|
|
918
|
+
The preview's **Print** button and `await printPreview()` print its current
|
|
919
|
+
rendered content with the file title. Native browser Print selects the open
|
|
920
|
+
preview ahead of the editor. Printing uses the shared
|
|
921
|
+
[`PrintView.js`](runtime-modules.md#printviewjs) owner; accessible HTML frames
|
|
922
|
+
are copied from their current rendered document, never substituted with source
|
|
923
|
+
text. Explicit printing waits for images/fonts and HTML frame readiness.
|
|
924
|
+
Native PDF and inaccessible embedded viewers require their own print command.
|
|
925
|
+
`true` means the browser print dialog was requested, not that paper or a PDF
|
|
926
|
+
was produced. Closed, destroyed, or unavailable previews return `false`;
|
|
927
|
+
preparation failures reject and the visible control reports a concise failure.
|
|
928
|
+
|
|
929
|
+
`await close()` cancels pending presentation work and closes delete, file, and
|
|
930
|
+
directory dialogs in that order. A settled preview keeps its rendered content,
|
|
931
|
+
media, and printing available until the file dialog actually closes; refusing
|
|
932
|
+
or failing to close leaves the still-visible preview usable. Actual file-dialog
|
|
933
|
+
closure releases its preview resources. The method returns `false` on
|
|
934
|
+
refused/failed closure or after destruction. The manager stays
|
|
935
|
+
reusable; a later opening can use it again. Already accepted upload/deletion
|
|
936
|
+
writes complete through the storage owner without reopening closed dialogs.
|
|
937
|
+
|
|
903
938
|
Events: `file-manager-ready`, `file-manager-select`, `file-manager-open`, `file-manager-action`.
|
|
904
939
|
|
|
905
940
|
Shared dependencies: [`DBOPFS.js`](runtime-modules.md#dbopfsjs), [`File.js`](runtime-entities.md#filejs), [`MD.js`](runtime-modules.md#mdjs), [`WaitForComponent.js`](runtime-modules.md#waitforcomponentjs).
|
|
@@ -1048,8 +1083,26 @@ inside an application-supplied bounded area.
|
|
|
1048
1083
|
|
|
1049
1084
|
### Public surface
|
|
1050
1085
|
|
|
1051
|
-
Methods/properties: `configure()`, `focus()`, `clear()`, `
|
|
1052
|
-
`destroy()`, `value`, `entryTitle`, `options`.
|
|
1086
|
+
Methods/properties: `configure()`, `focus()`, `clear()`, `insertMarkdown(text)`,
|
|
1087
|
+
`saveEntry()`, `print()`, `destroy()`, `value`, `entryTitle`, `options`.
|
|
1088
|
+
|
|
1089
|
+
`insertMarkdown(text)` replaces the current source selection with the exact
|
|
1090
|
+
supplied string, places the caret after it, and emits the ordinary change
|
|
1091
|
+
event. It preserves the source viewport and normal preview/save lifecycle.
|
|
1092
|
+
It returns `false` when read-only or destroyed and throws `TypeError` for a
|
|
1093
|
+
non-string. The application owns the inserted Markdown and any related data.
|
|
1094
|
+
|
|
1095
|
+
The visible **Print** control and `await print()` print the complete rendered
|
|
1096
|
+
Markdown with `entryTitle`, independently of saving. Native browser Print uses
|
|
1097
|
+
that same registered view unless an open file preview takes precedence.
|
|
1098
|
+
The SDK copies current rendered DOM/styles into a temporary print-only view,
|
|
1099
|
+
leaving the editor's source, controls, and screen layout in place. Explicit
|
|
1100
|
+
printing waits for resource readiness; native `beforeprint` is synchronous
|
|
1101
|
+
and uses the currently rendered content. `print()` returns `false` when the
|
|
1102
|
+
view is unavailable, rejects preparation failures, and returns `true` only
|
|
1103
|
+
when the browser dialog was requested. Completion of physical printing or PDF
|
|
1104
|
+
saving is not observable through this method. See
|
|
1105
|
+
[`PrintView.js`](runtime-modules.md#printviewjs).
|
|
1053
1106
|
|
|
1054
1107
|
`configure({fit:true,followPreview:true})` opts into the two independent
|
|
1055
1108
|
behaviors. Both options default to `false`; omitted options retain their
|
|
@@ -1087,7 +1140,7 @@ lists, quotes, and tables follow their block, while invisible source positions
|
|
|
1087
1140
|
use a nearby available rendered block rather than exact glyph geometry.
|
|
1088
1141
|
|
|
1089
1142
|
Public CSS parts are `editor`, `title`, `toolbar`, `input`, `preview`,
|
|
1090
|
-
`actions`, `status`, and `save-action`. Applications can make the title
|
|
1143
|
+
`actions`, `status`, `print-action`, and `save-action`. Applications can make the title
|
|
1091
1144
|
borderless and compact through `::part(title)` while retaining its native
|
|
1092
1145
|
editing behavior and visible keyboard focus. These parts are styling hooks,
|
|
1093
1146
|
not slots or replacement controls.
|
|
@@ -109,6 +109,7 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
109
109
|
| [`PersistentAIChatSession.js`](#persistentaichatsessionjs) | esm | Adds explicit retained-history/memory policy to complete configured chat without changing DBOPFS or ChatEntity semantics. | Browser / native WebView with DBOPFS and configured chat | Retained context commits atomically; `persist:false` turns are one-operation-only. |
|
|
110
110
|
| [`PreferenceStore.js`](#preferencestorejs) | esm | Loads and updates schema-defined app preferences through native storage with a narrow browser fallback. | Browser/native hybrid | Complete ordinary values remain mutable; setAll uses one optional atomic adapter batch for every selected value when advertised, otherwise performs complete ordered serial writes, and only exact unsupported native capability changes future operations to the browser fallback. |
|
|
111
111
|
| [`PreparedSpeech.js`](#preparedspeechjs) | esm | Owns detached ordered preparation, semantic audio reuse, and per-caller cancellation behind AI.prepareTTS. | Browser / native WebView with injected synthesis and optional DBOPFS | Complete original inputs, ordered audio metadata, durable reuse, and observable preparation results. |
|
|
112
|
+
| [`PrintView.js`](#printviewjs) | esm | Prints current rendered content and title through one document-owned print lifecycle. | Browser / supported native WebView print implementation | Complete rendered snapshot, preparation cancellation, resource lifetime, and honest request result. |
|
|
112
113
|
| [`QRCode.min.js`](#qrcodeminjs) | classic-script | Vendored QRCode generator for DOM, canvas, SVG, and image output. | Browser vendor script | Vendor-native. |
|
|
113
114
|
| [`Questionnaire.js`](#questionnairejs) | esm | Evaluates whether a one-time questionnaire prompt is due without performing the prompt. | Cross-host | Normalized conservative boolean. |
|
|
114
115
|
| [`RecordLinkIndex.js`](#recordlinkindexjs) | esm | Parses record links and builds their normalized index. | Cross-host | Fully normalized. |
|
|
@@ -3251,6 +3252,69 @@ import {prepareSpeech} from '/arcane/modules/PreparedSpeech.js';
|
|
|
3251
3252
|
console.log(typeof prepareSpeech); // function
|
|
3252
3253
|
```
|
|
3253
3254
|
|
|
3255
|
+
## PrintView.js
|
|
3256
|
+
|
|
3257
|
+
### Overview
|
|
3258
|
+
|
|
3259
|
+
Shared rendered-print owner used by Markdown Editor and File Manager. It
|
|
3260
|
+
captures the current DOM and computed styles, including accessible rendered
|
|
3261
|
+
HTML frames, complete text, selected images, and the current title. A temporary
|
|
3262
|
+
print-only surface expands scrollable content without editing the live screen.
|
|
3263
|
+
|
|
3264
|
+
### Public surface
|
|
3265
|
+
|
|
3266
|
+
Named `createPrintView({host,content,title,active,priority=0,signal,onError,retain})`
|
|
3267
|
+
returns `{print,destroy}`. `host` is a connected element; synchronous callbacks
|
|
3268
|
+
return the rendered content node, string title, and whether the view is active.
|
|
3269
|
+
Optional `retain()` returns a resource-release callback. It keeps owned media
|
|
3270
|
+
available until preparation is cancelled or the browser emits `afterprint`.
|
|
3271
|
+
|
|
3272
|
+
`await print()` selects that view, waits for accessible HTML frame, image, and
|
|
3273
|
+
font readiness, and requests the browser print dialog. It returns `false` when
|
|
3274
|
+
the view is unavailable or preparation is cancelled, returns `true` for a dialog
|
|
3275
|
+
request, and rejects preparation errors. It cannot confirm physical printing
|
|
3276
|
+
or PDF saving. Overlapping print sessions on the same document reject.
|
|
3277
|
+
|
|
3278
|
+
One native `beforeprint`/`afterprint` registration serves each document. Native
|
|
3279
|
+
Print chooses the highest-priority visible active view, most recently registered
|
|
3280
|
+
on ties. File preview uses priority `1`; editor uses `0`. Native `beforeprint`
|
|
3281
|
+
is synchronous: it snapshots currently rendered content, cannot await a newly
|
|
3282
|
+
loading resource, and cannot cancel the browser's dialog. `onError(error)` or
|
|
3283
|
+
the developer console receives complete preparation failures.
|
|
3284
|
+
|
|
3285
|
+
`destroy()` unregisters the view and cancels pending preparation. Once the
|
|
3286
|
+
dialog has been requested, its snapshot and retained media remain until
|
|
3287
|
+
`afterprint`. Import alone creates no listener, provider, storage, or print job.
|
|
3288
|
+
|
|
3289
|
+
Exact exports: `createPrintView`.
|
|
3290
|
+
|
|
3291
|
+
### Availability and normalization
|
|
3292
|
+
|
|
3293
|
+
**Browser and native WebViews with a print implementation.** Requires DOM,
|
|
3294
|
+
CSSOM, FontFace/Image readiness, and browser print events. No Core capability.
|
|
3295
|
+
Cross-origin/inaccessible frames, native PDF frames, and object/embed viewers
|
|
3296
|
+
must use their owning viewer's print command; the helper does not replace their
|
|
3297
|
+
content with raw source or claim an unrendered document was printed. Font
|
|
3298
|
+
sources in embedded documents must be accessible for snapshot preparation.
|
|
3299
|
+
|
|
3300
|
+
### Example
|
|
3301
|
+
|
|
3302
|
+
```javascript
|
|
3303
|
+
import {createPrintView} from '/arcane/modules/PrintView.js';
|
|
3304
|
+
|
|
3305
|
+
const ledger = document.querySelector('#moon-library-ledger');
|
|
3306
|
+
const printing = createPrintView({
|
|
3307
|
+
host:ledger,
|
|
3308
|
+
content:() => ledger,
|
|
3309
|
+
title:() => 'Books overdue on the Moon',
|
|
3310
|
+
active:() => true
|
|
3311
|
+
});
|
|
3312
|
+
document.querySelector('#print-ledger').onclick = async function printLedger(){
|
|
3313
|
+
try { await printing.print(); }
|
|
3314
|
+
catch(error) { console.error('Unable to print the ledger:', error); }
|
|
3315
|
+
};
|
|
3316
|
+
```
|
|
3317
|
+
|
|
3254
3318
|
## QRCode.min.js
|
|
3255
3319
|
|
|
3256
3320
|
### Overview
|
package/package.json
CHANGED
|
@@ -31,12 +31,16 @@
|
|
|
31
31
|
let content=null;
|
|
32
32
|
let fileManager=null;
|
|
33
33
|
let operationGeneration=0;
|
|
34
|
+
let openController = null;
|
|
35
|
+
let closingTask = null;
|
|
34
36
|
let destroyed=false;
|
|
35
37
|
|
|
36
38
|
host.beforeOpen=is.function(host.beforeOpen)
|
|
37
39
|
?host.beforeOpen
|
|
38
40
|
:async function beforeOpen(){};
|
|
39
41
|
host.open=openData;
|
|
42
|
+
host.close = closeData;
|
|
43
|
+
host.printPreview=printPreview;
|
|
40
44
|
host.destroy=destroy;
|
|
41
45
|
|
|
42
46
|
openButton.innerText=host.dataset.button||'View Data';
|
|
@@ -52,80 +56,159 @@
|
|
|
52
56
|
{signal:lifecycleController.signal}
|
|
53
57
|
);
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
dataModal.addEventListener(
|
|
60
|
+
'modal-closed',
|
|
61
|
+
function closeDataFromModal(event) {
|
|
62
|
+
if (event.target === dataModal && !closingTask) {
|
|
63
|
+
closeData();
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{signal: lifecycleController.signal}
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
async function openData() {
|
|
70
|
+
if (destroyed) {
|
|
57
71
|
return false;
|
|
58
72
|
}
|
|
59
|
-
const
|
|
60
|
-
await
|
|
61
|
-
if(destroyed||generation!==operationGeneration){
|
|
73
|
+
const requestedGeneration=operationGeneration;
|
|
74
|
+
if (closingTask && !await closingTask) {
|
|
62
75
|
return false;
|
|
63
76
|
}
|
|
64
|
-
|
|
65
|
-
const reload=Boolean(content);
|
|
66
|
-
|
|
67
|
-
const modal=await waitForComponent(
|
|
68
|
-
dataModal,
|
|
69
|
-
{
|
|
70
|
-
methods:['populate','open'],
|
|
71
|
-
property:'ready',
|
|
72
|
-
event:'modal-ready',
|
|
73
|
-
signal:lifecycleController.signal
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
if(destroyed||generation!==operationGeneration){
|
|
77
|
+
if (destroyed||requestedGeneration!==operationGeneration) {
|
|
77
78
|
return false;
|
|
78
79
|
}
|
|
80
|
+
const generation = ++operationGeneration;
|
|
81
|
+
openController?.abort('data-view-open-replaced');
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
openController = controller;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
await host.beforeOpen();
|
|
87
|
+
if (destroyed || generation !== operationGeneration) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
const reload = Boolean(content);
|
|
92
|
+
const modal = await waitForComponent(
|
|
93
|
+
dataModal,
|
|
94
|
+
{
|
|
95
|
+
methods: ['populate', 'open'],
|
|
96
|
+
property: 'ready',
|
|
97
|
+
event: 'modal-ready',
|
|
98
|
+
signal: controller.signal
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
if (destroyed || generation !== operationGeneration) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
83
104
|
|
|
84
|
-
|
|
105
|
+
if (!content) {
|
|
106
|
+
content = document.createElement('section');
|
|
107
|
+
fileManager = document.createElement('html-import');
|
|
108
|
+
|
|
109
|
+
const heading = document.createElement('h1');
|
|
110
|
+
|
|
111
|
+
heading.innerText = host.dataset.title || 'Data';
|
|
112
|
+
fileManager.className = 'file-manager';
|
|
113
|
+
forwardPreviewOptions();
|
|
114
|
+
fileManager.dataset.dirs = host.dataset.dirs || '';
|
|
115
|
+
fileManager.dataset.layout = host.dataset.layout || 'files';
|
|
116
|
+
fileManager.setAttribute(
|
|
117
|
+
'href',
|
|
118
|
+
new URL('./file-manager.html', componentHref).href
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
content.append(heading, fileManager);
|
|
122
|
+
await modal.populate(content, false);
|
|
123
|
+
if (destroyed || generation !== operationGeneration) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
85
127
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
128
|
+
if (reload) {
|
|
129
|
+
forwardPreviewOptions();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const manager = await waitForComponent(
|
|
133
|
+
fileManager,
|
|
134
|
+
{
|
|
135
|
+
methods: ['loadAll'],
|
|
136
|
+
property: 'ready',
|
|
137
|
+
event: 'file-manager-ready',
|
|
138
|
+
signal: controller.signal
|
|
139
|
+
}
|
|
94
140
|
);
|
|
141
|
+
if (destroyed || generation !== operationGeneration) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
95
144
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
145
|
+
if (reload) {
|
|
146
|
+
await manager.loadAll();
|
|
147
|
+
if (destroyed || generation !== operationGeneration) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return await modal.open();
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (controller.signal.aborted) {
|
|
99
155
|
return false;
|
|
100
156
|
}
|
|
157
|
+
throw error;
|
|
158
|
+
} finally {
|
|
159
|
+
if (openController === controller) {
|
|
160
|
+
openController = null;
|
|
161
|
+
}
|
|
101
162
|
}
|
|
163
|
+
}
|
|
102
164
|
|
|
103
|
-
|
|
104
|
-
|
|
165
|
+
async function closeData() {
|
|
166
|
+
if (destroyed) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
operationGeneration += 1;
|
|
170
|
+
openController?.abort('data-view-closed');
|
|
171
|
+
openController = null;
|
|
172
|
+
if (closingTask) {
|
|
173
|
+
return closingTask;
|
|
105
174
|
}
|
|
106
175
|
|
|
107
|
-
const
|
|
108
|
-
fileManager
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
176
|
+
const childClosing = is.function(fileManager?.close)
|
|
177
|
+
? fileManager.close()
|
|
178
|
+
: Promise.resolve(true);
|
|
179
|
+
closingTask = Promise.resolve(childClosing)
|
|
180
|
+
.then(closeDataAfterChildren)
|
|
181
|
+
.catch(
|
|
182
|
+
function reportDataCloseFailure(error) {
|
|
183
|
+
arcaneLogging.error('Unable to close data view:', error);
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
try {
|
|
188
|
+
return await closingTask;
|
|
189
|
+
} finally {
|
|
190
|
+
closingTask = null;
|
|
118
191
|
}
|
|
192
|
+
}
|
|
119
193
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
194
|
+
async function closeDataAfterChildren(childrenClosed) {
|
|
195
|
+
if (childrenClosed === false || destroyed) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (is.function(dataModal.close)) {
|
|
199
|
+
const closed = await dataModal.close();
|
|
200
|
+
if (closed === false) {
|
|
123
201
|
return false;
|
|
124
202
|
}
|
|
125
203
|
}
|
|
204
|
+
return !destroyed && dataModal.opened !== true;
|
|
205
|
+
}
|
|
126
206
|
|
|
127
|
-
|
|
128
|
-
|
|
207
|
+
async function printPreview(){
|
|
208
|
+
if(destroyed||dataModal.opened!==true||!is.function(fileManager?.printPreview)){
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
return fileManager.printPreview();
|
|
129
212
|
}
|
|
130
213
|
|
|
131
214
|
function forwardPreviewOptions(){
|
|
@@ -146,6 +229,8 @@
|
|
|
146
229
|
}
|
|
147
230
|
destroyed=true;
|
|
148
231
|
operationGeneration+=1;
|
|
232
|
+
openController?.abort('data-view-destroyed');
|
|
233
|
+
openController = null;
|
|
149
234
|
lifecycleController.abort('data-view-destroyed');
|
|
150
235
|
fileManager?.destroy?.();
|
|
151
236
|
dataModal.destroy?.();
|