@sciflow/editor-start 0.0.1-beta → 0.0.1-beta2

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 (43) hide show
  1. package/README.md +34 -0
  2. package/dist/bundle/sciflow-editor.css +1 -1
  3. package/dist/bundle/sciflow-editor.js +7643 -5555
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/lib/citation-source-adapter.d.ts +22 -2
  8. package/dist/lib/citation-source-adapter.d.ts.map +1 -1
  9. package/dist/lib/citation-source-adapter.js +104 -48
  10. package/dist/lib/drag-preview.d.ts +13 -0
  11. package/dist/lib/drag-preview.d.ts.map +1 -0
  12. package/dist/lib/drag-preview.js +36 -0
  13. package/dist/lib/editor-element.d.ts +16 -1
  14. package/dist/lib/editor-element.d.ts.map +1 -1
  15. package/dist/lib/editor-element.js +107 -30
  16. package/dist/lib/format-bar.d.ts +7 -0
  17. package/dist/lib/format-bar.d.ts.map +1 -1
  18. package/dist/lib/format-bar.js +79 -10
  19. package/dist/lib/outline.d.ts +10 -5
  20. package/dist/lib/outline.d.ts.map +1 -1
  21. package/dist/lib/outline.js +112 -1
  22. package/dist/lib/reference-list.d.ts.map +1 -1
  23. package/dist/lib/reference-list.js +2 -0
  24. package/dist/lib/selection-editor.d.ts +67 -5
  25. package/dist/lib/selection-editor.d.ts.map +1 -1
  26. package/dist/lib/selection-editor.js +1060 -125
  27. package/dist/lib/selection-transform-registry.d.ts +16 -0
  28. package/dist/lib/selection-transform-registry.d.ts.map +1 -0
  29. package/dist/lib/selection-transform-registry.js +24 -0
  30. package/dist/lib/selection-ui-renderer.d.ts +21 -0
  31. package/dist/lib/selection-ui-renderer.d.ts.map +1 -0
  32. package/dist/lib/selection-ui-renderer.js +244 -0
  33. package/dist/lib/selection-widget-host.d.ts +67 -0
  34. package/dist/lib/selection-widget-host.d.ts.map +1 -0
  35. package/dist/lib/selection-widget-host.js +151 -0
  36. package/dist/lib/selection-widget-registry.d.ts +16 -0
  37. package/dist/lib/selection-widget-registry.d.ts.map +1 -0
  38. package/dist/lib/selection-widget-registry.js +30 -0
  39. package/dist/lib/test-fixtures/soak-documents.d.ts +13 -0
  40. package/dist/lib/test-fixtures/soak-documents.d.ts.map +1 -0
  41. package/dist/lib/test-fixtures/soak-documents.js +69 -0
  42. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  43. package/package.json +9 -5
package/dist/index.d.ts CHANGED
@@ -13,5 +13,5 @@ export * from './lib/selection-editor.js';
13
13
  export * from './lib/theme.js';
14
14
  export { defaultCitationSourceAdapter, getCitationSourceAdapter, setCitationSourceAdapter, type CitationItem, type CitationSourceEditorAdapter, type CitationSourceEditorContext, } from './lib/citation-source-adapter.js';
15
15
  export { SourceField } from '@sciflow/editor-core';
16
- export { citationFeature, createFigureFeature, listFeature, blockquoteFeature, copyPasteFeature, installMockImageServer, configureImageUploadHandlers, requestImageFile, uploadImageFile, promptForFigureOptions, figureFeature, headingFeature, markFormattingFeature, tableFeature, } from '@sciflow/editor-core';
16
+ export { citationFeature, crossReferenceFeature, createFigureFeature, listFeature, blockquoteFeature, copyPasteFeature, installMockImageServer, configureImageUploadHandlers, requestImageFile, uploadImageFile, promptForFigureOptions, figureFeature, footnoteFeature, headingFeature, markFormattingFeature, mathFeature, tableFeature, } from '@sciflow/editor-core';
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,YAAY,EACjB,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,GACjC,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,4BAA4B,EAC5B,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,YAAY,GACb,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,YAAY,EACjB,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,GACjC,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,4BAA4B,EAC5B,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,YAAY,GACb,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -14,4 +14,4 @@ export * from './lib/theme.js';
14
14
  export { defaultCitationSourceAdapter, getCitationSourceAdapter, setCitationSourceAdapter, } from './lib/citation-source-adapter.js';
15
15
  // Convenience re-export: allow downstream bundles to pull SourceField from here.
16
16
  export { SourceField } from '@sciflow/editor-core';
17
- export { citationFeature, createFigureFeature, listFeature, blockquoteFeature, copyPasteFeature, installMockImageServer, configureImageUploadHandlers, requestImageFile, uploadImageFile, promptForFigureOptions, figureFeature, headingFeature, markFormattingFeature, tableFeature, } from '@sciflow/editor-core';
17
+ export { citationFeature, crossReferenceFeature, createFigureFeature, listFeature, blockquoteFeature, copyPasteFeature, installMockImageServer, configureImageUploadHandlers, requestImageFile, uploadImageFile, promptForFigureOptions, figureFeature, footnoteFeature, headingFeature, markFormattingFeature, mathFeature, tableFeature, } from '@sciflow/editor-core';
@@ -7,12 +7,32 @@
7
7
  */
8
8
  import type { CitationItem } from '@sciflow/editor-core';
9
9
  export type { CitationItem };
10
+ /**
11
+ * Reference entry for the citation ID dropdown (id + optional display label).
12
+ */
13
+ export interface CitationReferenceOption {
14
+ id: string;
15
+ rawCitation?: string;
16
+ }
10
17
  /**
11
18
  * Context passed to the adapter when rendering or updating.
12
19
  */
13
20
  export interface CitationSourceEditorContext {
14
- /** Apply updated source string to the node via command API. */
15
- applySource: (encoded: string | null) => boolean;
21
+ /**
22
+ * Apply updated source string to the node via command API (immediate commit).
23
+ * Optional when using draft flow; then only onSourceChange is used until an explicit Update.
24
+ */
25
+ applySource?: (encoded: string | null) => boolean;
26
+ /**
27
+ * Draft callback: called when source fields change without applying to the document.
28
+ * When provided, the adapter uses this instead of applySource for field changes.
29
+ */
30
+ onSourceChange?: (encoded: string | null) => void;
31
+ /**
32
+ * Optional list of references available in the editor (for ID dropdown).
33
+ * When provided, the default adapter renders a dropdown for the ID field instead of a text input.
34
+ */
35
+ getReferences?: () => CitationReferenceOption[];
16
36
  }
17
37
  /**
18
38
  * Adapter interface for rendering and editing citation source (CSL citation items).
@@ -1 +1 @@
1
- {"version":3,"file":"citation-source-adapter.d.ts","sourceRoot":"","sources":["../../src/lib/citation-source-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,+DAA+D;IAC/D,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;CAClD;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,MAAM,CACJ,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,EAAE,2BAA2B,GACnC,IAAI,CAAC;IAER;;;;;OAKG;IACH,MAAM,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAEnG;;;OAGG;IACH,OAAO,CAAC,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CACxC;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,2BA0G1C,CAAC;AAKF;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI,GAAG,IAAI,CAE1F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,2BAA2B,CAEtE"}
1
+ {"version":3,"file":"citation-source-adapter.d.ts","sourceRoot":"","sources":["../../src/lib/citation-source-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,YAAY,EAAE,YAAY,EAAE,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;IAClD;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,uBAAuB,EAAE,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,MAAM,CACJ,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,EAAE,2BAA2B,GACnC,IAAI,CAAC;IAER;;;;;OAKG;IACH,MAAM,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAEnG;;;OAGG;IACH,OAAO,CAAC,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CACxC;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,2BAiL1C,CAAC;AAKF;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI,GAAG,IAAI,CAE1F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,2BAA2B,CAEtE"}
@@ -24,61 +24,117 @@ export const defaultCitationSourceAdapter = {
24
24
  })
25
25
  .filter((item) => item !== null);
26
26
  const encoded = SourceField.toString(normalized);
27
- context.applySource(encoded);
27
+ if (context.onSourceChange) {
28
+ context.onSourceChange(encoded);
29
+ }
30
+ else if (context.applySource) {
31
+ context.applySource(encoded);
32
+ }
28
33
  };
29
- items.forEach((item, index) => {
30
- const section = document.createElement('div');
31
- section.className = 'citation-source-item';
32
- section.setAttribute('data-citation-index', String(index));
33
- const fields = [
34
- { key: 'id', label: 'ID', type: 'text', required: true },
35
- { key: 'label', label: 'Label', type: 'text' },
36
- { key: 'locator', label: 'Locator', type: 'text' },
37
- { key: 'prefix', label: 'Prefix', type: 'text' },
38
- { key: 'suffix', label: 'Suffix', type: 'text' },
39
- { key: 'suppress-author', label: 'Suppress author', type: 'checkbox' },
40
- { key: 'author-only', label: 'Author only', type: 'checkbox' },
41
- ];
42
- fields.forEach(({ key, label, type }) => {
43
- const fieldDiv = document.createElement('div');
44
- fieldDiv.className = 'citation-source-field';
45
- fieldDiv.setAttribute('data-field', key);
46
- const idAttr = `citation-${index}-${key}`;
47
- const labelEl = document.createElement('label');
48
- labelEl.htmlFor = idAttr;
49
- labelEl.className = 'selection-editor-attr-label';
50
- labelEl.textContent = `${label}:`;
51
- fieldDiv.appendChild(labelEl);
52
- if (type === 'checkbox') {
53
- const input = document.createElement('input');
54
- input.type = 'checkbox';
55
- input.id = idAttr;
56
- input.className = 'selection-editor-input';
57
- const val = item[key];
58
- input.checked = val === 1 || val === true;
59
- input.addEventListener('change', () => {
60
- items[index][key] = input.checked ? 1 : undefined;
61
- apply();
34
+ const appendTextInput = (fieldDiv, idAttr, item, key, index, itemsList, applyFn) => {
35
+ const input = document.createElement('input');
36
+ input.type = 'text';
37
+ input.id = idAttr;
38
+ input.className = 'selection-editor-input';
39
+ input.placeholder = 'No value';
40
+ const val = item[key];
41
+ input.value = typeof val === 'string' ? val : val != null ? String(val) : '';
42
+ input.addEventListener('change', () => {
43
+ const v = input.value.trim();
44
+ itemsList[index][key] = v || undefined;
45
+ applyFn();
46
+ });
47
+ fieldDiv.appendChild(input);
48
+ };
49
+ const idFieldOnly = [
50
+ { key: 'id', label: 'ID', type: 'text', required: true },
51
+ ];
52
+ const extraFields = [
53
+ { key: 'label', label: 'Label', type: 'text' },
54
+ { key: 'locator', label: 'Locator', type: 'text' },
55
+ { key: 'prefix', label: 'Prefix', type: 'text' },
56
+ { key: 'suffix', label: 'Suffix', type: 'text' },
57
+ { key: 'suppress-author', label: 'Suppress author', type: 'checkbox' },
58
+ { key: 'author-only', label: 'Author only', type: 'checkbox' },
59
+ ];
60
+ const renderField = (section, item, index, key, label, type) => {
61
+ const fieldDiv = document.createElement('div');
62
+ fieldDiv.className =
63
+ type === 'checkbox' ? 'citation-source-field citation-source-field--checkbox' : 'citation-source-field';
64
+ fieldDiv.setAttribute('data-field', key);
65
+ const idAttr = `citation-${index}-${key}`;
66
+ const labelEl = document.createElement('label');
67
+ labelEl.htmlFor = idAttr;
68
+ labelEl.className = 'selection-editor-attr-label';
69
+ labelEl.textContent = `${label}:`;
70
+ fieldDiv.appendChild(labelEl);
71
+ if (type === 'checkbox') {
72
+ const input = document.createElement('input');
73
+ input.type = 'checkbox';
74
+ input.id = idAttr;
75
+ input.className = 'selection-editor-input';
76
+ const val = item[key];
77
+ input.checked = val === 1 || val === true;
78
+ input.addEventListener('change', () => {
79
+ items[index][key] = input.checked ? 1 : undefined;
80
+ apply();
81
+ });
82
+ fieldDiv.appendChild(input);
83
+ }
84
+ else if (key === 'id' && context.getReferences) {
85
+ const refs = context.getReferences();
86
+ if (refs.length > 0) {
87
+ const select = document.createElement('select');
88
+ select.id = idAttr;
89
+ select.className = 'selection-editor-input selection-editor-select';
90
+ const currentId = typeof item.id === 'string' ? item.id : item.id != null ? String(item.id) : '';
91
+ const emptyOpt = document.createElement('option');
92
+ emptyOpt.value = '';
93
+ emptyOpt.textContent = 'No value';
94
+ select.appendChild(emptyOpt);
95
+ refs.forEach((ref) => {
96
+ const opt = document.createElement('option');
97
+ opt.value = ref.id;
98
+ opt.textContent = (ref.rawCitation ?? ref.id).trim() || ref.id;
99
+ select.appendChild(opt);
62
100
  });
63
- fieldDiv.appendChild(input);
64
- }
65
- else {
66
- const input = document.createElement('input');
67
- input.type = 'text';
68
- input.id = idAttr;
69
- input.className = 'selection-editor-input';
70
- input.placeholder = 'No value';
71
- const val = item[key];
72
- input.value = typeof val === 'string' ? val : val != null ? String(val) : '';
73
- input.addEventListener('change', () => {
74
- const v = input.value.trim();
101
+ select.value = refs.some((r) => r.id === currentId) ? currentId : '';
102
+ select.addEventListener('change', () => {
103
+ const v = select.value.trim();
75
104
  items[index][key] = v || undefined;
76
105
  apply();
77
106
  });
78
- fieldDiv.appendChild(input);
107
+ fieldDiv.appendChild(select);
108
+ }
109
+ else {
110
+ appendTextInput(fieldDiv, idAttr, item, key, index, items, apply);
79
111
  }
80
- section.appendChild(fieldDiv);
112
+ }
113
+ else {
114
+ appendTextInput(fieldDiv, idAttr, item, key, index, items, apply);
115
+ }
116
+ section.appendChild(fieldDiv);
117
+ };
118
+ items.forEach((item, index) => {
119
+ const section = document.createElement('div');
120
+ section.className = 'citation-source-item';
121
+ section.setAttribute('data-citation-index', String(index));
122
+ idFieldOnly.forEach(({ key, label, type }) => {
123
+ renderField(section, item, index, key, label, type);
124
+ });
125
+ const details = document.createElement('details');
126
+ details.className = 'citation-source-details';
127
+ const summary = document.createElement('summary');
128
+ summary.className = 'citation-source-details-summary';
129
+ summary.textContent = 'Label, locator, prefix…';
130
+ details.appendChild(summary);
131
+ const detailsBody = document.createElement('div');
132
+ detailsBody.className = 'citation-source-details-body';
133
+ extraFields.forEach(({ key, label, type }) => {
134
+ renderField(detailsBody, item, index, key, label, type);
81
135
  });
136
+ details.appendChild(detailsBody);
137
+ section.appendChild(details);
82
138
  if (items.length > 1) {
83
139
  const removeBtn = document.createElement('button');
84
140
  removeBtn.type = 'button';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Configure a transparent, offset drag image for HTML5 drag operations.
3
+ * Makes it easier to see the drop cursor while dragging references or headings.
4
+ *
5
+ * @param event - The dragstart event
6
+ * @param options - Optional opacity (0–1), vertical offset (positive = above cursor), and scale (0–1)
7
+ */
8
+ export declare function setTransparentDragImage(event: DragEvent, options?: {
9
+ opacity?: number;
10
+ offsetY?: number;
11
+ scale?: number;
12
+ }): void;
13
+ //# sourceMappingURL=drag-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-preview.d.ts","sourceRoot":"","sources":["../../src/lib/drag-preview.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACnE,IAAI,CA+BN"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Configure a transparent, offset drag image for HTML5 drag operations.
3
+ * Makes it easier to see the drop cursor while dragging references or headings.
4
+ *
5
+ * @param event - The dragstart event
6
+ * @param options - Optional opacity (0–1), vertical offset (positive = above cursor), and scale (0–1)
7
+ */
8
+ export function setTransparentDragImage(event, options = {}) {
9
+ const transfer = event.dataTransfer;
10
+ const target = event.target;
11
+ if (!transfer || !(target instanceof HTMLElement))
12
+ return;
13
+ const { opacity = 0.5, offsetY = 20, scale = 1 } = options;
14
+ const clone = target.cloneNode(true);
15
+ clone.style.opacity = String(opacity);
16
+ clone.style.transform = `scale(${scale})`;
17
+ clone.style.transformOrigin = 'bottom center';
18
+ clone.style.position = 'absolute';
19
+ clone.style.top = '-9999px';
20
+ clone.style.left = '-9999px';
21
+ clone.style.pointerEvents = 'none';
22
+ clone.style.maxWidth = '18rem';
23
+ clone.style.fontSize = '0.65rem';
24
+ const root = target.getRootNode();
25
+ const container = root instanceof ShadowRoot ? root : document.body;
26
+ container.appendChild(clone);
27
+ const rect = clone.getBoundingClientRect();
28
+ const x = Math.floor(rect.width / 2);
29
+ const y = Math.floor(rect.height) + offsetY;
30
+ try {
31
+ transfer.setDragImage(clone, x, y);
32
+ }
33
+ finally {
34
+ requestAnimationFrame(() => clone.remove());
35
+ }
36
+ }
@@ -108,6 +108,14 @@ export declare class SciFlowEditorElement extends LitElement {
108
108
  headingText: string;
109
109
  /** Paragraph text used when no initial content is provided. */
110
110
  placeholder: string;
111
+ /**
112
+ * Max-width of the ProseMirror content area.
113
+ * Approximates page-like text columns at 11pt:
114
+ * - 'narrow': narrow column (~52 characters per line)
115
+ * - 'wide': normal column (~82 characters per line)
116
+ * Styles are applied to the shadow DOM.
117
+ */
118
+ editorWidth: 'narrow' | 'wide';
111
119
  private view;
112
120
  private editor?;
113
121
  private docUnsub?;
@@ -121,12 +129,17 @@ export declare class SciFlowEditorElement extends LitElement {
121
129
  private shadowStyleElements;
122
130
  private themeUnsub?;
123
131
  private themeStyleElements;
132
+ private _hostDragoverBound;
124
133
  /** Access the underlying ProseMirror view instance. */
125
134
  get editorView(): ReturnType<Editor['getView']> | null;
126
135
  /** Access SciFlow command helpers bound to the current editor view. */
127
136
  get commands(): CommandRunner | null;
128
137
  /** Get read-only access to the document structure for traversal. */
129
138
  get document(): ProsemirrorNode | null;
139
+ /** Get the current references (bibliography) stored with the document. */
140
+ get references(): SnapshotReference[];
141
+ /** Get the merged selection UI schema (Draft-07 + _ui_*), when available. */
142
+ getSelectionUiSchema(): import("@sciflow/editor-core").SelectionUiSchema | undefined;
130
143
  /** Get position utilities for coordinate mapping. */
131
144
  get positions(): {
132
145
  coordsAtPos: (pos: number) => {
@@ -185,6 +198,8 @@ export declare class SciFlowEditorElement extends LitElement {
185
198
  private isExternalDocUpdate;
186
199
  private extractDocFromInput;
187
200
  private buildSyncUpdate;
201
+ private isNoopSyncUpdate;
202
+ private deepEqualsJSON;
188
203
  /**
189
204
  * Determine which document should be loaded on startup.
190
205
  * Preference order: externally supplied JSON, provided PM node, fallback.
@@ -243,9 +258,9 @@ export declare class SciFlowEditorElement extends LitElement {
243
258
  private destroyEditor;
244
259
  private capturePendingOps;
245
260
  private applyShadowStyles;
261
+ private getEditorWidthStyles;
246
262
  private normalizeShadowStyles;
247
263
  private extractCssFromSheet;
248
- private debugTestLog;
249
264
  }
250
265
  declare global {
251
266
  interface HTMLElementTagNameMap {
@@ -1 +1 @@
1
- {"version":3,"file":"editor-element.d.ts","sourceRoot":"","sources":["../../src/lib/editor-element.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor-element.d.ts","sourceRoot":"","sources":["../../src/lib/editor-element.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@
26
26
  import { __decorate } from "tslib";
27
27
  import { css, html, unsafeCSS, LitElement } from 'lit';
28
28
  import { customElement, property } from 'lit/decorators.js';
29
- import { Editor, SourceField, citationFeature, figureFeature, headingFeature, markFormattingFeature, tableFeature, } from '@sciflow/editor-core';
29
+ import { Editor, SourceField, citationFeature, crossReferenceFeature, figureFeature, footnoteFeature, headingFeature, markFormattingFeature, mathFeature, tableFeature, } from '@sciflow/editor-core';
30
30
  import { manuscript as manuscriptSchema } from '@sciflow/schema-prosemirror';
31
31
  import editorStyles from './editor-element.css?inline';
32
32
  import { applyThemeStylesToRoot, subscribeToSciFlowTheme } from './theme.js';
@@ -73,6 +73,14 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
73
73
  this.headingText = 'Moby-Dick: A Study in Obsession';
74
74
  /** Paragraph text used when no initial content is provided. */
75
75
  this.placeholder = 'Introduce Ishmael and the enigmatic Captain Ahab…';
76
+ /**
77
+ * Max-width of the ProseMirror content area.
78
+ * Approximates page-like text columns at 11pt:
79
+ * - 'narrow': narrow column (~52 characters per line)
80
+ * - 'wide': normal column (~82 characters per line)
81
+ * Styles are applied to the shadow DOM.
82
+ */
83
+ this.editorWidth = 'wide';
76
84
  this.view = null;
77
85
  this.pendingOps = [];
78
86
  this.pendingOpsFromTransform = false;
@@ -80,6 +88,7 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
80
88
  this.deferInitializationForDoc = false;
81
89
  this.shadowStyleElements = [];
82
90
  this.themeStyleElements = [];
91
+ this._hostDragoverBound = null;
83
92
  }
84
93
  get shadowStyles() {
85
94
  return this._shadowStyles;
@@ -102,6 +111,14 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
102
111
  get document() {
103
112
  return this.editor?.getDocument() ?? null;
104
113
  }
114
+ /** Get the current references (bibliography) stored with the document. */
115
+ get references() {
116
+ return this.editor?.getReferences() ?? [];
117
+ }
118
+ /** Get the merged selection UI schema (Draft-07 + _ui_*), when available. */
119
+ getSelectionUiSchema() {
120
+ return this.editor?.getSelectionUiSchema?.();
121
+ }
105
122
  /** Get position utilities for coordinate mapping. */
106
123
  get positions() {
107
124
  return {
@@ -138,23 +155,22 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
138
155
  }
139
156
  connectedCallback() {
140
157
  super.connectedCallback();
158
+ this._hostDragoverBound = (e) => {
159
+ if (!e.dataTransfer?.types || !this.contains(e.target))
160
+ return;
161
+ const types = Array.from(e.dataTransfer.types);
162
+ const allow = types.includes('application/x-sciflow-reference') ||
163
+ types.includes('application/x-sciflow-cross-reference');
164
+ if (!allow)
165
+ return;
166
+ e.preventDefault();
167
+ e.dataTransfer.dropEffect = 'copy';
168
+ };
169
+ this.addEventListener('dragover', this._hostDragoverBound, { capture: true });
141
170
  this.themeUnsub = subscribeToSciFlowTheme((cssTexts) => {
142
171
  this.themeStyleElements = applyThemeStylesToRoot(this.renderRoot, this.themeStyleElements, cssTexts);
143
172
  this.applyShadowStyles();
144
173
  });
145
- queueMicrotask(() => {
146
- this.debugTestLog('connected microtask', { hasEditor: !!this.editor });
147
- if (this.editor) {
148
- return;
149
- }
150
- try {
151
- const initialDoc = this.resolveInitialDoc();
152
- this.dispatchEditorChange(initialDoc.toJSON(), [], []);
153
- }
154
- catch {
155
- // Ignore errors during eager ready dispatch; initialization will retry in firstUpdated.
156
- }
157
- });
158
174
  }
159
175
  /**
160
176
  * React to property changes coming from the host application.
@@ -173,6 +189,9 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
173
189
  if (changedProperties.has('shadowStyles') && !this._shadowStylesAppliedExternally) {
174
190
  this.applyShadowStyles();
175
191
  }
192
+ if (changedProperties.has('editorWidth')) {
193
+ this.applyShadowStyles();
194
+ }
176
195
  // Reset flag for next update
177
196
  if (changedProperties.has('shadowStyles')) {
178
197
  this._shadowStylesAppliedExternally = false;
@@ -186,6 +205,10 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
186
205
  * Other frameworks should execute the same logic in their unmount hook.
187
206
  */
188
207
  disconnectedCallback() {
208
+ if (this._hostDragoverBound) {
209
+ this.removeEventListener('dragover', this._hostDragoverBound, { capture: true });
210
+ this._hostDragoverBound = null;
211
+ }
189
212
  super.disconnectedCallback();
190
213
  this.themeUnsub?.();
191
214
  this.themeUnsub = undefined;
@@ -215,7 +238,16 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
215
238
  * Resolves a mount point, creates the editor instance, and wires listeners.
216
239
  */
217
240
  getDefaultFeatures() {
218
- return [citationFeature, markFormattingFeature, headingFeature, figureFeature, tableFeature];
241
+ return [
242
+ citationFeature,
243
+ crossReferenceFeature,
244
+ footnoteFeature,
245
+ markFormattingFeature,
246
+ headingFeature,
247
+ figureFeature,
248
+ tableFeature,
249
+ mathFeature,
250
+ ];
219
251
  }
220
252
  getActiveFeatures() {
221
253
  return this.features ?? this.getDefaultFeatures();
@@ -224,13 +256,11 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
224
256
  return this.doc === null && this.initialContent === null;
225
257
  }
226
258
  async initializeView() {
227
- this.debugTestLog('initializeView invoked');
228
259
  if (this.view) {
229
260
  return;
230
261
  }
231
262
  const mountPoint = this.renderRoot.querySelector('.editor');
232
263
  if (!mountPoint) {
233
- this.debugTestLog('initializeView: mount point missing');
234
264
  return;
235
265
  }
236
266
  const initialDoc = this.resolveInitialDoc();
@@ -263,11 +293,7 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
263
293
  this.editor = editor;
264
294
  editor.mount(mountPoint);
265
295
  this.view = editor.getView();
266
- this.debugTestLog('editor mounted', { hasView: !!this.view });
267
- const runner = editor.getCommands();
268
- this.debugTestLog('command keys', runner ? Object.keys(runner.commands) : null);
269
296
  this.docUnsub = editor.onDoc((doc) => {
270
- this.debugTestLog('dispatching editor-change', { ops: this.pendingOps.length });
271
297
  const files = editor.getFiles();
272
298
  this.dispatchEditorChange(doc, this.pendingOps, files);
273
299
  this.pendingOps = [];
@@ -277,6 +303,7 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
277
303
  this.dispatchSelectionChange(selection);
278
304
  });
279
305
  this.validationUnsub = editor.onValidation(() => undefined);
306
+ this.dispatchEditorChange(initialDoc.toJSON(), [], editor.getFiles());
280
307
  this.dispatchEditorReady();
281
308
  this.initialSelection = undefined;
282
309
  }
@@ -294,6 +321,9 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
294
321
  if (!update) {
295
322
  return;
296
323
  }
324
+ if (this.isNoopSyncUpdate(update)) {
325
+ return;
326
+ }
297
327
  this.pendingOps = [];
298
328
  this.pendingOpsFromTransform = false;
299
329
  this.editor.updateFromSync(update);
@@ -366,6 +396,46 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
366
396
  }
367
397
  return { doc: input };
368
398
  }
399
+ isNoopSyncUpdate(update) {
400
+ const editor = this.editor;
401
+ if (!editor) {
402
+ return false;
403
+ }
404
+ if (update.doc !== undefined && !this.deepEqualsJSON(update.doc, editor.getDoc())) {
405
+ return false;
406
+ }
407
+ if (update.selection !== undefined) {
408
+ const current = editor.getSelection();
409
+ if (!current) {
410
+ return false;
411
+ }
412
+ if (update.selection.anchor !== current.anchor || update.selection.head !== current.head) {
413
+ return false;
414
+ }
415
+ }
416
+ if (update.version !== undefined && update.version !== editor.getVersion()) {
417
+ return false;
418
+ }
419
+ if (update.files !== undefined && !this.deepEqualsJSON(update.files, editor.getFiles())) {
420
+ return false;
421
+ }
422
+ if (update.references !== undefined &&
423
+ !this.deepEqualsJSON(update.references, editor.getReferences())) {
424
+ return false;
425
+ }
426
+ return true;
427
+ }
428
+ deepEqualsJSON(left, right) {
429
+ if (left === right) {
430
+ return true;
431
+ }
432
+ try {
433
+ return JSON.stringify(left) === JSON.stringify(right);
434
+ }
435
+ catch {
436
+ return false;
437
+ }
438
+ }
369
439
  /**
370
440
  * Determine which document should be loaded on startup.
371
441
  * Preference order: externally supplied JSON, provided PM node, fallback.
@@ -482,7 +552,6 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
482
552
  * Applications can listen and update their stores or routing state.
483
553
  */
484
554
  dispatchEditorChange(doc, operations, files) {
485
- this.debugTestLog('editor-change event', { doc, operations });
486
555
  this.dispatchEvent(new CustomEvent('editor-change', {
487
556
  detail: { doc, operations, files, references: this.editor?.getReferences() ?? [] },
488
557
  bubbles: true,
@@ -601,6 +670,10 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
601
670
  }
602
671
  this.shadowStyleElements = [];
603
672
  const cssTexts = this.normalizeShadowStyles(this.shadowStyles);
673
+ const widthCss = this.getEditorWidthStyles();
674
+ if (widthCss) {
675
+ cssTexts.push(widthCss);
676
+ }
604
677
  if (cssTexts.length === 0) {
605
678
  return;
606
679
  }
@@ -611,6 +684,15 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
611
684
  this.shadowStyleElements.push(styleEl);
612
685
  }
613
686
  }
687
+ getEditorWidthStyles() {
688
+ const isNarrow = this.editorWidth === 'narrow';
689
+ return `.ProseMirror {
690
+ font-size: 11pt;
691
+ max-width: ${isNarrow ? '52ch' : '82ch'};
692
+ margin-left: auto;
693
+ margin-right: auto;
694
+ }`;
695
+ }
614
696
  normalizeShadowStyles(styles) {
615
697
  if (!styles) {
616
698
  return [];
@@ -648,14 +730,6 @@ let SciFlowEditorElement = class SciFlowEditorElement extends LitElement {
648
730
  return null;
649
731
  }
650
732
  }
651
- debugTestLog(message, payload) {
652
- const isDebug = (typeof process !== 'undefined' && process.env?.DEBUG_TESTS === 'true') ||
653
- (typeof import.meta !== 'undefined' && import.meta.env?.DEBUG_TESTS === 'true');
654
- if (!isDebug) {
655
- return;
656
- }
657
- console.log('[sciflow-editor]', message, payload ?? '');
658
- }
659
733
  };
660
734
  __decorate([
661
735
  property({ attribute: false })
@@ -675,6 +749,9 @@ __decorate([
675
749
  __decorate([
676
750
  property({ type: String })
677
751
  ], SciFlowEditorElement.prototype, "placeholder", void 0);
752
+ __decorate([
753
+ property({ type: String })
754
+ ], SciFlowEditorElement.prototype, "editorWidth", void 0);
678
755
  SciFlowEditorElement = __decorate([
679
756
  customElement('sciflow-editor')
680
757
  ], SciFlowEditorElement);