@jini-ai/ui 0.4.6 → 0.4.8
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/README.md +33 -0
- package/dist/features/admin-widgets/components/InfoTip.d.ts +23 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.d.ts +22 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.js +75 -28
- package/dist/features/admin-widgets/components/InfoTip.js +12 -4
- package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +72 -0
- package/dist/features/admin-widgets/components/InfoTip.rules.js +68 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.d.ts +36 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.d.ts +58 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +66 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.js +24 -0
- package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.d.ts +23 -0
- package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.js +28 -0
- package/dist/features/admin-widgets/index.d.ts +9 -0
- package/dist/features/admin-widgets/index.js +5 -0
- package/dist/features/execution/constants.js +11 -10
- package/dist/features/execution/http-adapter.d.ts +3 -1
- package/dist/features/execution/http-adapter.js +9 -4
- package/dist/features/execution/index.d.ts +1 -1
- package/dist/features/execution/index.js +1 -1
- package/dist/features/execution/react/components/ByokProviderForm.d.ts +18 -1
- package/dist/features/execution/react/components/ByokProviderForm.js +14 -16
- package/dist/features/execution/react/components/LocalCliAgentCard.d.ts +5 -1
- package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -87
- package/dist/features/execution/react/components/LocalCliAgentList.d.ts +4 -1
- package/dist/features/execution/react/components/LocalCliAgentList.js +13 -4
- package/dist/features/execution/react/components/LocalCliAgentSettings.d.ts +20 -0
- package/dist/features/execution/react/components/LocalCliAgentSettings.js +20 -0
- package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.d.ts +24 -0
- package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.js +27 -0
- package/dist/features/execution/react/hooks/useExecutionTab.js +10 -1
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.d.ts +48 -0
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +110 -0
- package/dist/features/execution/react/hooks/useLocalCliAgentList.d.ts +19 -0
- package/dist/features/execution/react/hooks/useLocalCliAgentList.js +13 -0
- package/dist/features/execution/rules.d.ts +13 -0
- package/dist/features/execution/rules.js +14 -0
- package/dist/features/execution/types.d.ts +2 -0
- package/dist/features/html-editor/canvas-embed-placeholders.d.ts +13 -1
- package/dist/features/html-editor/canvas-embed-placeholders.js +61 -12
- package/dist/features/html-editor/dom.d.ts +5 -0
- package/dist/features/html-editor/dom.js +10 -0
- package/dist/features/html-editor/editor-blocks.d.ts +71 -0
- package/dist/features/html-editor/editor-blocks.js +185 -0
- package/dist/features/html-editor/editor-serialization.d.ts +24 -0
- package/dist/features/html-editor/editor-serialization.js +110 -0
- package/dist/features/html-editor/index.d.ts +5 -0
- package/dist/features/html-editor/index.js +3 -0
- package/dist/features/html-editor/protected-elements.d.ts +64 -0
- package/dist/features/html-editor/protected-elements.js +189 -0
- package/dist/features/html-editor/react/components/InteractiveHtmlEditor.d.ts +6 -4
- package/dist/features/html-editor/react/components/InteractiveHtmlEditor.js +3 -3
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.d.ts +9 -1
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +107 -196
- package/dist/features/html-editor/source-splice.d.ts +23 -0
- package/dist/features/html-editor/source-splice.js +45 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ar.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.bn.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.de.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.en.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.es.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fa.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fr.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hi.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hu.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.id.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.it.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ko.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pl.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ru.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.th.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.tr.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.uk.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ur.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +4 -0
- package/dist/features/interactive-ui/interactive-ui.css +1 -1
- package/dist/features/interactive-ui/providers/native/data-table.js +8 -1
- package/dist/features/interactive-ui/providers/native/data-table.manifest.d.ts +3 -5
- package/dist/features/interactive-ui/providers/native/data-table.manifest.js +5 -7
- package/dist/features/interactive-ui/providers/recharts/bar-chart.js +8 -3
- package/dist/features/interactive-ui/providers/recharts/chart-config.d.ts +40 -0
- package/dist/features/interactive-ui/providers/recharts/chart-config.js +32 -0
- package/dist/features/interactive-ui/providers/recharts/chart-tokens.d.ts +18 -12
- package/dist/features/interactive-ui/providers/recharts/chart-tokens.js +6 -11
- package/dist/features/interactive-ui/providers/recharts/chart.d.ts +31 -0
- package/dist/features/interactive-ui/providers/recharts/chart.js +34 -0
- package/dist/features/interactive-ui/providers/recharts/line-chart.js +10 -3
- package/dist/features/interactive-ui/providers/recharts/pie-chart.js +8 -3
- package/dist/features/interactive-ui/providers/shadcn/button.d.ts +1 -1
- package/dist/features/interactive-ui/providers/shadcn/data-table.d.ts +5 -1
- package/dist/features/interactive-ui/providers/shadcn/data-table.js +26 -2
- package/dist/features/interactive-ui/providers/shadcn/data-table.manifest.d.ts +8 -1
- package/dist/features/interactive-ui/providers/shadcn/data-table.manifest.js +6 -3
- package/dist/features/interactive-ui/table-data.d.ts +25 -0
- package/dist/features/interactive-ui/table-data.js +36 -0
- package/dist/features/mcp-ui/escape.js +2 -6
- package/dist/features/mcp-ui/sandbox-proxy-link-forwarder.d.ts +26 -0
- package/dist/features/mcp-ui/sandbox-proxy-link-forwarder.js +40 -0
- package/dist/features/mcp-ui/sandbox-proxy.d.ts +5 -1
- package/dist/features/mcp-ui/sandbox-proxy.js +11 -0
- package/dist/features/mcp-ui/surfaces/bridge.js +9 -3
- package/dist/features/mcp-ui/surfaces/document.d.ts +11 -4
- package/dist/features/mcp-ui/surfaces/document.js +25 -3
- package/dist/features/mcp-ui/surfaces/outcome.js +1 -1
- package/dist/features/media-providers/constants.d.ts +0 -7
- package/dist/features/media-providers/constants.js +7 -15
- package/dist/features/media-providers/react/components/MediaProvidersTab.js +3 -2
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +6 -3
- package/dist/features/memory/dependencies.d.ts +2 -0
- package/dist/features/memory/dependencies.js +9 -25
- package/dist/features/memory/index.d.ts +1 -0
- package/dist/features/memory/index.js +1 -0
- package/dist/features/memory/react/MemoryPorts.d.ts +17 -0
- package/dist/features/memory/react/MemoryPorts.js +15 -0
- package/dist/features/memory/react/hooks/useMemoryConfig.hooks.d.ts +2 -2
- package/dist/features/memory/react/hooks/useMemoryConfig.hooks.js +7 -7
- package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.d.ts +2 -3
- package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.js +4 -5
- package/dist/features/memory/react/hooks/useMemoryEntries.hooks.d.ts +2 -3
- package/dist/features/memory/react/hooks/useMemoryEntries.hooks.js +4 -5
- package/dist/features/memory/react/hooks/useMemoryExtractions.hooks.js +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.js +5 -3
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.d.ts +11 -0
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +212 -0
- package/dist/features/panel-kit/fetch-query/binding.react.d.ts +17 -0
- package/dist/features/panel-kit/fetch-query/binding.react.js +24 -0
- package/dist/features/panel-kit/fetch-query/environment.browser.d.ts +1 -1
- package/dist/features/panel-kit/fetch-query/index.d.ts +6 -3
- package/dist/features/panel-kit/fetch-query/index.js +2 -1
- package/dist/features/panel-kit/fetch-query/tanstack.d.ts +8 -0
- package/dist/features/panel-kit/fetch-query/tanstack.js +4 -0
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.d.ts +3 -1
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +9 -2
- package/dist/features/settings/dialog/styles/settings-dialog.css +169 -21
- package/dist/features/tabbed-dialog/styles/tabbed-dialog.css +91 -0
- package/dist/react/components/RemixIcon.d.ts +1 -41
- package/dist/react/components/RemixIcon.js +3 -176
- package/dist/react/components/RemixIcon.stylesheet.d.ts +84 -0
- package/dist/react/components/RemixIcon.stylesheet.js +208 -0
- package/dist/react/components/remixicon-font-recovery.d.ts +55 -0
- package/dist/react/components/remixicon-font-recovery.js +110 -0
- package/dist/styles/admin.css +8 -2
- package/package.json +25 -8
- package/dist/features/panel-kit/fetch-query/cache.d.ts +0 -123
- package/dist/features/panel-kit/fetch-query/cache.js +0 -231
- package/dist/features/panel-kit/fetch-query/types.d.ts +0 -91
- package/dist/features/panel-kit/fetch-query/types.js +0 -2
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { findEditorBlockOpening } from './editor-blocks.js';
|
|
2
|
+
export const PROTECTED_ELEMENT_TYPE = 'protected-element';
|
|
3
|
+
/** Distinguishable from an ordinary best-effort RTE timeout: never persist a damaged raw shell. */
|
|
4
|
+
export class EditorSourceError extends Error {
|
|
5
|
+
code = 'EDITOR_SOURCE_INTEGRITY';
|
|
6
|
+
constructor({ message = "Can't edit this source visually. Use HTML." } = {}, _options = {}) { super(message); this.name = 'EditorSourceError'; }
|
|
7
|
+
}
|
|
8
|
+
export function isEditorSourceError({ error }, _options = {}) {
|
|
9
|
+
return !!error && typeof error === 'object' && 'code' in error && error.code === 'EDITOR_SOURCE_INTEGRITY';
|
|
10
|
+
}
|
|
11
|
+
/** Source lives only on the component model, so clone and undo carry it with ordinary model state. */
|
|
12
|
+
export function protectedElementHtml({ component }, _options = {}) {
|
|
13
|
+
const original = component.get('originalHtml');
|
|
14
|
+
if (typeof original !== 'string' || original.length === 0)
|
|
15
|
+
throw new EditorSourceError();
|
|
16
|
+
return original;
|
|
17
|
+
}
|
|
18
|
+
function visit(component, callback) {
|
|
19
|
+
callback(component);
|
|
20
|
+
component.components().models.forEach(child => visit(child, callback));
|
|
21
|
+
}
|
|
22
|
+
/** Check surviving instances before any export or no-op flush; deletion itself is allowed. */
|
|
23
|
+
export function assertProtectedSourceMetadata({ editor }, _options = {}) {
|
|
24
|
+
const wrapper = editor.getWrapper();
|
|
25
|
+
if (wrapper)
|
|
26
|
+
visit(wrapper, component => {
|
|
27
|
+
if (component.is(PROTECTED_ELEMENT_TYPE))
|
|
28
|
+
protectedElementHtml({ component }, {});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Verify initial parser ownership before the first visual edit; recovered/lost shells fail closed. */
|
|
32
|
+
export function assertPreparedSourceModel({ editor, sourcePlan }, _options = {}) {
|
|
33
|
+
const actual = [];
|
|
34
|
+
const wrapper = editor.getWrapper();
|
|
35
|
+
if (!wrapper)
|
|
36
|
+
throw new EditorSourceError();
|
|
37
|
+
visit(wrapper, component => {
|
|
38
|
+
if (component.is(PROTECTED_ELEMENT_TYPE))
|
|
39
|
+
actual.push(protectedElementHtml({ component }, {}));
|
|
40
|
+
});
|
|
41
|
+
if (actual.length !== sourcePlan.instances.length || actual.some((html, i) => html !== sourcePlan.instances[i].originalHtml)) {
|
|
42
|
+
throw new EditorSourceError();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Text ancestors must not sync canvas-only card chrome back into a model during RTE close. */
|
|
46
|
+
export function protectTextAncestors({ editor }, _options = {}) {
|
|
47
|
+
const wrapper = editor.getWrapper();
|
|
48
|
+
if (!wrapper)
|
|
49
|
+
return;
|
|
50
|
+
visit(wrapper, component => {
|
|
51
|
+
if (!component.is(PROTECTED_ELEMENT_TYPE))
|
|
52
|
+
return;
|
|
53
|
+
for (let parent = component.parent(); parent; parent = parent.parent()) {
|
|
54
|
+
if (parent.is('text'))
|
|
55
|
+
parent.set('editable', false, { silent: true });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** Same canvas card path, addressed through model metadata rather than authored/public selectors. */
|
|
60
|
+
export function protectedCanvasDescriber({ editor }, _options = {}) {
|
|
61
|
+
const descriptors = new Map();
|
|
62
|
+
const wrapper = editor.getWrapper();
|
|
63
|
+
if (wrapper)
|
|
64
|
+
visit(wrapper, component => {
|
|
65
|
+
if (!component.is(PROTECTED_ELEMENT_TYPE) || component.get('sourceNonvisual'))
|
|
66
|
+
return;
|
|
67
|
+
const el = component.getEl();
|
|
68
|
+
const descriptor = component.get('placeholderDescriptor');
|
|
69
|
+
if (el && descriptor)
|
|
70
|
+
descriptors.set(el, descriptor);
|
|
71
|
+
});
|
|
72
|
+
return el => descriptors.get(el);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Registers the `protected-element` component type so any parsed element `isProtectedElement`
|
|
76
|
+
* recognizes becomes one atomic block: its content can never be edited (excluded from RTE
|
|
77
|
+
* content-editing, including as a nested island inside a `text` component), dropped into, or styled,
|
|
78
|
+
* but the element itself is selectable and can be deliberately moved, copied or deleted like any other
|
|
79
|
+
* block. Selectable matters for safety: a non-selectable element hands a click to its nearest
|
|
80
|
+
* selectable ancestor, so clicking an embed selected the block around it and Delete then removed that
|
|
81
|
+
* block together with the embed. Pair it with `applyCanvasEmbedPlaceholders`, which makes the marker
|
|
82
|
+
* the clickable surface of its card. Passed as a `plugins` entry so it registers before
|
|
83
|
+
* `editor.setComponents` parses the initial `html` (see `initInteractiveHtmlEditor` below).
|
|
84
|
+
*
|
|
85
|
+
* @complexity O(1) — one type registration; the per-element check GrapesJS then runs during parsing
|
|
86
|
+
* is O(1) per element (whatever `isProtectedElement` costs), not owned by this function.
|
|
87
|
+
* @overallScore 100
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* One protected type for runtime roots, host embeds and nonvisual atoms. Registration precedes
|
|
91
|
+
* parsing; isComponent resolves mount-private tokens to metadata and supplies empty children.
|
|
92
|
+
*/
|
|
93
|
+
export function registerProtectedElementType({ editor, sourcePlan }, options = {}) {
|
|
94
|
+
const command = 'jini:protected-edit-html';
|
|
95
|
+
const requestEditHtml = options.onRequestEditHtml;
|
|
96
|
+
if (requestEditHtml)
|
|
97
|
+
editor.Commands.add(command, {
|
|
98
|
+
async run() {
|
|
99
|
+
try {
|
|
100
|
+
await options.beforeRequestEditHtml?.();
|
|
101
|
+
const selected = editor.getSelected();
|
|
102
|
+
const wrapper = editor.getWrapper();
|
|
103
|
+
if (!selected?.is(PROTECTED_ELEMENT_TYPE) || !wrapper || selected.get('sourceNonvisual'))
|
|
104
|
+
return;
|
|
105
|
+
const original = protectedElementHtml({ component: selected }, {});
|
|
106
|
+
const html = wrapper.getInnerHTML();
|
|
107
|
+
// Search only exact authored slices. Copies share bytes, so count preceding equal instances
|
|
108
|
+
// in model order; no mapping export mode or persistent source tokens are needed.
|
|
109
|
+
let copiesBefore = 0;
|
|
110
|
+
let reached = false;
|
|
111
|
+
visit(wrapper, component => {
|
|
112
|
+
if (component === selected)
|
|
113
|
+
reached = true;
|
|
114
|
+
else if (!reached && component.is(PROTECTED_ELEMENT_TYPE) && protectedElementHtml({ component }, {}) === original)
|
|
115
|
+
copiesBefore++;
|
|
116
|
+
});
|
|
117
|
+
let start = -1;
|
|
118
|
+
for (let i = 0; i <= copiesBefore; i++)
|
|
119
|
+
start = html.indexOf(original, start + 1);
|
|
120
|
+
if (start < 0)
|
|
121
|
+
throw new EditorSourceError();
|
|
122
|
+
const tagName = selected.get('sourceTagName');
|
|
123
|
+
const id = selected.get('sourceId');
|
|
124
|
+
let occurrenceIndex = 0;
|
|
125
|
+
for (;;) {
|
|
126
|
+
const range = findEditorBlockOpening({ html, target: { occurrenceIndex, tagName, ...(id ? { id } : {}) } }, {});
|
|
127
|
+
if (!range || range.start > start)
|
|
128
|
+
throw new EditorSourceError();
|
|
129
|
+
if (range.start === start)
|
|
130
|
+
break;
|
|
131
|
+
occurrenceIndex++;
|
|
132
|
+
}
|
|
133
|
+
await requestEditHtml({ occurrenceIndex, tagName, ...(id ? { id } : {}) }, {});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
options.onSerializationError?.(error instanceof EditorSourceError ? error : new EditorSourceError());
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
editor.Components.addType(PROTECTED_ELEMENT_TYPE, {
|
|
141
|
+
isComponent(el) {
|
|
142
|
+
const token = typeof el.getAttribute === 'function' ? el.getAttribute(sourcePlan.markerAttribute)
|
|
143
|
+
: el.attributes?.[sourcePlan.markerAttribute];
|
|
144
|
+
if (token === null || token === undefined)
|
|
145
|
+
return undefined;
|
|
146
|
+
const instance = sourcePlan.instances[Number(token)];
|
|
147
|
+
if (!instance || String(Number(token)) !== token)
|
|
148
|
+
throw new EditorSourceError();
|
|
149
|
+
return {
|
|
150
|
+
type: PROTECTED_ELEMENT_TYPE, originalHtml: instance.originalHtml, sourceTagName: instance.tagName,
|
|
151
|
+
sourceId: instance.id, sourceNonvisual: instance.nonvisual, placeholderDescriptor: instance.descriptor,
|
|
152
|
+
components: [], content: '',
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
model: {
|
|
156
|
+
defaults: {
|
|
157
|
+
editable: false, droppable: false, stylable: false, resizable: false, traits: [],
|
|
158
|
+
layerable: false, badgable: false, selectable: true, hoverable: true, highlightable: true,
|
|
159
|
+
removable: true, draggable: true, copyable: true,
|
|
160
|
+
},
|
|
161
|
+
init() {
|
|
162
|
+
// Keep default move/copy/delete toolbar commands, then append the host navigation action.
|
|
163
|
+
if (!this.get('sourceNonvisual') && options.onRequestEditHtml) {
|
|
164
|
+
const toolbar = (this.get('toolbar') ?? []);
|
|
165
|
+
this.set('toolbar', [...toolbar.filter(item => item.command !== command), {
|
|
166
|
+
label: options.editHtmlLabel ?? 'Edit HTML', command,
|
|
167
|
+
// GrapesJS sizes every toolbar item as a 26px icon square; a text label overflowed past the
|
|
168
|
+
// toolbar (and the canvas edge on full-width blocks), so this item sizes to its label.
|
|
169
|
+
attributes: {
|
|
170
|
+
title: options.editHtmlLabel ?? 'Edit HTML', 'aria-label': options.editHtmlLabel ?? 'Edit HTML',
|
|
171
|
+
style: 'width:auto;white-space:nowrap;padding:5px 8px',
|
|
172
|
+
},
|
|
173
|
+
}], { silent: true });
|
|
174
|
+
}
|
|
175
|
+
if (this.get('sourceNonvisual'))
|
|
176
|
+
this.set({ selectable: false, draggable: false, hoverable: false, copyable: false }, { silent: true });
|
|
177
|
+
},
|
|
178
|
+
toHTML() { return protectedElementHtml({ component: this }, {}); },
|
|
179
|
+
},
|
|
180
|
+
view: {
|
|
181
|
+
onRender() {
|
|
182
|
+
this.el.setAttribute('contenteditable', 'false');
|
|
183
|
+
if (this.model.get('sourceNonvisual'))
|
|
184
|
+
this.el.style.setProperty('display', 'none', 'important');
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=protected-elements.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'grapesjs/dist/css/grapes.min.css';
|
|
2
2
|
import type { CanvasEmbedPlaceholderDescriptor } from '../../canvas-embed-placeholders.js';
|
|
3
3
|
import type { CanvasStyling } from '../../canvas-style.js';
|
|
4
|
+
import { type InteractiveEditorOptions } from '../hooks/useInteractiveHtmlEditor.js';
|
|
4
5
|
/**
|
|
5
6
|
* @file A visual, click-into-text editing surface for a bespoke HTML document, built on GrapesJS
|
|
6
7
|
* (MIT). Renders `html` like a live preview but lets the operator click into rendered text and edit
|
|
@@ -32,7 +33,8 @@ import type { CanvasStyling } from '../../canvas-style.js';
|
|
|
32
33
|
* is an optional predicate the caller supplies to turn specific elements (identified however the
|
|
33
34
|
* caller likes) into atomic blocks: their content can never be edited, dropped into or styled, but a
|
|
34
35
|
* click selects the element itself (never the block around it), and it can be deliberately moved,
|
|
35
|
-
* copied or deleted.
|
|
36
|
+
* copied or deleted. Runtime/native and author-opted blocks are always protected; the predicate
|
|
37
|
+
* adds host-owned embed recognition.
|
|
36
38
|
* `describeEmbedPlaceholder` is the same idea for a second, independent concern: recognizing an
|
|
37
39
|
* unresolved embed marker and labeling it for `../../canvas-embed-placeholders.ts`'s explicit
|
|
38
40
|
* placeholder card. See `@jini-ai/admin/react`'s `InteractiveHtmlEditor` for a worked example of both:
|
|
@@ -66,7 +68,7 @@ import type { CanvasStyling } from '../../canvas-style.js';
|
|
|
66
68
|
* guaranteed by WHEN it is applied (against the live canvas, after GrapesJS has already parsed
|
|
67
69
|
* `html`), not by a strip-on-export step.
|
|
68
70
|
*/
|
|
69
|
-
export interface InteractiveHtmlEditorProps {
|
|
71
|
+
export interface InteractiveHtmlEditorProps extends InteractiveEditorOptions {
|
|
70
72
|
/** The document to load into the editor. Read once, at mount — see this file's header and
|
|
71
73
|
* `react/hooks/useInteractiveHtmlEditor.ts` for why. */
|
|
72
74
|
html: string;
|
|
@@ -79,7 +81,7 @@ export interface InteractiveHtmlEditorProps {
|
|
|
79
81
|
/** Identifies elements whose content must never be edited or dropped into inside the editor. Each
|
|
80
82
|
* one is selectable as a single block that can be deliberately moved, copied or deleted. Read once, at mount, same as `html`. Predicates that check attributes should use
|
|
81
83
|
* `hasAttributeOnAnyNodeShape` (exported alongside this component) rather than `el.hasAttribute`
|
|
82
|
-
* directly — see that helper's own doc for why. Omit
|
|
84
|
+
* directly — see that helper's own doc for why. Omit for runtime/native blocks only. */
|
|
83
85
|
isProtectedElement?: (el: Element) => boolean;
|
|
84
86
|
/** CSS to render the edited document against inside the editing canvas, so the operator sees
|
|
85
87
|
* roughly what the document publishes as rather than browser defaults. Read once, at mount, same
|
|
@@ -90,7 +92,7 @@ export interface InteractiveHtmlEditorProps {
|
|
|
90
92
|
* fallback content it authored) — see `../../canvas-embed-placeholders.ts`'s own file header for
|
|
91
93
|
* the export-safety argument. Read once, at mount, same as `isProtectedElement`. Returning
|
|
92
94
|
* `undefined` for an element means "not a marker this host owns" — left completely untouched.
|
|
93
|
-
* Omit
|
|
95
|
+
* Omit for runtime/native cards only. This component has the same zero knowledge
|
|
94
96
|
* of any host's marker convention that `isProtectedElement` documents above. */
|
|
95
97
|
describeEmbedPlaceholder?: (el: Element) => CanvasEmbedPlaceholderDescriptor | undefined;
|
|
96
98
|
}
|
|
@@ -8,10 +8,10 @@ const GJS_STYLE_VARS = {
|
|
|
8
8
|
'--gjs-left-width': '0px',
|
|
9
9
|
'--gjs-canvas-top': '0px',
|
|
10
10
|
};
|
|
11
|
-
export const InteractiveHtmlEditor = forwardRef(function InteractiveHtmlEditor({ html, onChange, className, isProtectedElement, canvasStyling, describeEmbedPlaceholder }, ref) {
|
|
12
|
-
const { containerRef, flush } = useInteractiveHtmlEditor(html, onChange, isProtectedElement, canvasStyling, describeEmbedPlaceholder);
|
|
11
|
+
export const InteractiveHtmlEditor = forwardRef(function InteractiveHtmlEditor({ html, onChange, className, isProtectedElement, canvasStyling, describeEmbedPlaceholder, onRequestEditHtml, translate, onSerializationError }, ref) {
|
|
12
|
+
const { containerRef, flush, sourceError } = useInteractiveHtmlEditor(html, onChange, isProtectedElement, canvasStyling, describeEmbedPlaceholder, { onRequestEditHtml, translate, onSerializationError });
|
|
13
13
|
useImperativeHandle(ref, () => ({ flush }), [flush]);
|
|
14
14
|
const wrapperClassName = className ? `interactive-html-editor ${className}` : 'interactive-html-editor';
|
|
15
|
-
return _jsx("div", { ref: containerRef, className: wrapperClassName, style: GJS_STYLE_VARS });
|
|
15
|
+
return _jsx("div", { ref: containerRef, className: wrapperClassName, style: GJS_STYLE_VARS, children: sourceError && _jsx("p", { role: "alert", children: sourceError }) });
|
|
16
16
|
});
|
|
17
17
|
//# sourceMappingURL=InteractiveHtmlEditor.js.map
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type CanvasEmbedPlaceholderDescriptor } from '../../canvas-embed-placeholders.js';
|
|
2
2
|
import { type CanvasStyling } from '../../canvas-style.js';
|
|
3
|
+
import { type RequestEditHtml } from '../../editor-blocks.js';
|
|
4
|
+
import { EditorSourceError } from '../../protected-elements.js';
|
|
3
5
|
/**
|
|
4
6
|
* Owns one GrapesJS `Editor` instance for the lifetime of the calling component's mount. `onChange`
|
|
5
7
|
* fires with the editor's current serialized content (see `serializeWithSplice`) on every content
|
|
@@ -36,8 +38,14 @@ import { type CanvasStyling } from '../../canvas-style.js';
|
|
|
36
38
|
* beyond that.
|
|
37
39
|
* @overallScore 100
|
|
38
40
|
*/
|
|
39
|
-
export
|
|
41
|
+
export interface InteractiveEditorOptions {
|
|
42
|
+
onRequestEditHtml?: RequestEditHtml | undefined;
|
|
43
|
+
translate?: ((key: string) => string) | undefined;
|
|
44
|
+
onSerializationError?: ((error: EditorSourceError) => void) | undefined;
|
|
45
|
+
}
|
|
46
|
+
export declare function useInteractiveHtmlEditor(html: string, onChange: (html: string) => void, isProtectedElement?: (el: Element) => boolean, canvasStyling?: CanvasStyling, describeEmbedPlaceholder?: (el: Element) => CanvasEmbedPlaceholderDescriptor | undefined, options?: InteractiveEditorOptions): {
|
|
40
47
|
containerRef: import("react").RefObject<HTMLDivElement | null>;
|
|
41
48
|
flush: () => Promise<string | undefined>;
|
|
49
|
+
sourceError: string | undefined;
|
|
42
50
|
};
|
|
43
51
|
//# sourceMappingURL=useInteractiveHtmlEditor.d.ts.map
|