diff --git a/docs/dist/v1/chartifact.host.umd.js b/docs/dist/v1/chartifact.host.umd.js index 26cbea9c..a51216d3 100644 --- a/docs/dist/v1/chartifact.host.umd.js +++ b/docs/dist/v1/chartifact.host.umd.js @@ -3658,13 +3658,32 @@ ${guardedJs} return; } const message = event.data; - if (message.type == "hostRenderRequest") { - if (message.markdown) { - await host.render(message.title, message.markdown, void 0, false); - } else if (message.interactiveDocument) { - await host.render(message.title, void 0, message.interactiveDocument, false); + if (message.type === "hostRenderRequest") { + const renderMessage = message; + if (renderMessage.markdown) { + await host.render(renderMessage.title, renderMessage.markdown, void 0, false); + } else if (renderMessage.interactiveDocument) { + await host.render(renderMessage.title, void 0, renderMessage.interactiveDocument, false); } else { } + } else if (message.type === "hostToolbarControl") { + const toolbarMessage = message; + if (!host.toolbar) { + console.warn("Toolbar control message received but no toolbar is available"); + return; + } + if (toolbarMessage.showSource !== void 0) { + host.toolbar.setSourceVisibility(toolbarMessage.showSource); + } + if (toolbarMessage.showOrHideButtons !== void 0) { + host.toolbar.showOrHideButtons(toolbarMessage.showOrHideButtons); + } + if (toolbarMessage.setFilename !== void 0) { + host.toolbar.setFilename(toolbarMessage.setFilename); + } + if (toolbarMessage.showDownloadDialog !== void 0 && toolbarMessage.showDownloadDialog) { + host.toolbar.showDownloadDialog(); + } } } catch (error) { host.errorHandler( @@ -4290,6 +4309,34 @@ ${htmlJsonJs} this.props.downloadDisplay = ""; this.render(); } + showOrHideButtons(buttons) { + if (buttons.source !== void 0) { + this.props.tweakDisplay = buttons.source ? "" : "none"; + } + if (buttons.download !== void 0) { + this.props.downloadDisplay = buttons.download ? "" : "none"; + } + if (buttons.restart !== void 0) { + this.props.restartDisplay = buttons.restart ? "" : "none"; + } + this.render(); + } + setSourceVisibility(visible) { + const { textarea } = this.options; + if (!textarea) { + return; + } + textarea.style.display = visible ? "" : "none"; + } + setFilename(filename) { + this.filename = filename; + this.render(); + } + showDownloadDialog() { + if (this.props.downloadClick) { + this.props.downloadClick(); + } + } manageTextareaVisibilityForAgents() { const { textarea } = this.options; if (!textarea) { diff --git a/docs/dist/v1/chartifact.toolbar.umd.js b/docs/dist/v1/chartifact.toolbar.umd.js index ad3f123d..2d33f278 100644 --- a/docs/dist/v1/chartifact.toolbar.umd.js +++ b/docs/dist/v1/chartifact.toolbar.umd.js @@ -433,6 +433,34 @@ ${htmlJsonJs} this.props.downloadDisplay = ""; this.render(); } + showOrHideButtons(buttons) { + if (buttons.source !== void 0) { + this.props.tweakDisplay = buttons.source ? "" : "none"; + } + if (buttons.download !== void 0) { + this.props.downloadDisplay = buttons.download ? "" : "none"; + } + if (buttons.restart !== void 0) { + this.props.restartDisplay = buttons.restart ? "" : "none"; + } + this.render(); + } + setSourceVisibility(visible) { + const { textarea } = this.options; + if (!textarea) { + return; + } + textarea.style.display = visible ? "" : "none"; + } + setFilename(filename) { + this.filename = filename; + this.render(); + } + showDownloadDialog() { + if (this.props.downloadClick) { + this.props.downloadClick(); + } + } manageTextareaVisibilityForAgents() { const { textarea } = this.options; if (!textarea) { diff --git a/packages/common/src/messages.ts b/packages/common/src/messages.ts index 3f6d6d8f..87cfc6f2 100644 --- a/packages/common/src/messages.ts +++ b/packages/common/src/messages.ts @@ -42,6 +42,18 @@ export interface HostStatusMessage { details?: string; } +export interface HostToolbarControlMessage { + type: 'hostToolbarControl'; + showSource?: boolean; + showOrHideButtons?: { + source?: boolean; + download?: boolean; + restart?: boolean; + }; + showDownloadDialog?: boolean; + setFilename?: string; +} + export interface EditorReadyMessage { type: 'editorReady'; sender: string; diff --git a/packages/host-test/src/index.ts b/packages/host-test/src/index.ts index 78c8c03a..5faee300 100644 --- a/packages/host-test/src/index.ts +++ b/packages/host-test/src/index.ts @@ -7,7 +7,8 @@ const iframe = document.getElementById('host') as HTMLIFrameElement; window.addEventListener('message', (event) => { const hostStatusMessage = event.data as Chartifact.common.HostStatusMessage; if (hostStatusMessage.type === 'hostStatus' && hostStatusMessage.hostStatus === 'ready') { - const message: Chartifact.common.HostRenderRequestMessage = { + // First, send the render request + const renderMessage: Chartifact.common.HostRenderRequestMessage = { type: 'hostRenderRequest', title: 'sample', markdown: `# Auto-loaded Content @@ -55,6 +56,30 @@ The colors distinguish between different weather conditions such as sun, fog, dr } \`\`\` `}; - iframe.contentWindow.postMessage(message, '*'); + iframe.contentWindow.postMessage(renderMessage, '*'); + + // After a short delay, demonstrate toolbar control + setTimeout(() => { + const toolbarControlMessage: Chartifact.common.HostToolbarControlMessage = { + type: 'hostToolbarControl', + showSource: true, // Show the source textarea + setFilename: 'seattle-weather-demo', // Set a custom filename + showOrHideButtons: { // Control button visibility + source: true, + download: true, + restart: false + } + }; + iframe.contentWindow.postMessage(toolbarControlMessage, '*'); + }, 1000); + + // After another delay, demonstrate showing the download dialog + setTimeout(() => { + const showDownloadMessage: Chartifact.common.HostToolbarControlMessage = { + type: 'hostToolbarControl', + showDownloadDialog: true // Show the download popup dialog + }; + iframe.contentWindow.postMessage(showDownloadMessage, '*'); + }, 2500); } }); \ No newline at end of file diff --git a/packages/host/src/post-receive.ts b/packages/host/src/post-receive.ts index 04ee6175..4208a932 100644 --- a/packages/host/src/post-receive.ts +++ b/packages/host/src/post-receive.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. */ import { Listener } from './listener.js'; -import type { HostRenderRequestMessage } from 'common'; +import type { HostRenderRequestMessage, HostToolbarControlMessage } from 'common'; export function setupPostMessageHandling(host: Listener) { window.addEventListener('message', async (event) => { @@ -14,15 +14,37 @@ export function setupPostMessageHandling(host: Listener) { return; } - const message = event.data as HostRenderRequestMessage; - if (message.type == 'hostRenderRequest') { - if (message.markdown) { - await host.render( message.title, message.markdown, undefined, false); - } else if (message.interactiveDocument) { - await host.render( message.title, undefined, message.interactiveDocument, false); + const message = event.data; + + if (message.type === 'hostRenderRequest') { + const renderMessage = message as HostRenderRequestMessage; + if (renderMessage.markdown) { + await host.render(renderMessage.title, renderMessage.markdown, undefined, false); + } else if (renderMessage.interactiveDocument) { + await host.render(renderMessage.title, undefined, renderMessage.interactiveDocument, false); } else { //do nothing, as messages may be directed to the page for other purposes } + } else if (message.type === 'hostToolbarControl') { + const toolbarMessage = message as HostToolbarControlMessage; + if (!host.toolbar) { + console.warn('Toolbar control message received but no toolbar is available'); + return; + } + + // Apply toolbar controls + if (toolbarMessage.showSource !== undefined) { + host.toolbar.setSourceVisibility(toolbarMessage.showSource); + } + if (toolbarMessage.showOrHideButtons !== undefined) { + host.toolbar.showOrHideButtons(toolbarMessage.showOrHideButtons); + } + if (toolbarMessage.setFilename !== undefined) { + host.toolbar.setFilename(toolbarMessage.setFilename); + } + if (toolbarMessage.showDownloadDialog !== undefined && toolbarMessage.showDownloadDialog) { + host.toolbar.showDownloadDialog(); + } } } catch (error) { host.errorHandler( diff --git a/packages/toolbar/src/toolbar.tsx b/packages/toolbar/src/toolbar.tsx index 0a01910d..57857719 100644 --- a/packages/toolbar/src/toolbar.tsx +++ b/packages/toolbar/src/toolbar.tsx @@ -214,6 +214,39 @@ export class Toolbar { this.render(); } + showOrHideButtons(buttons: { source?: boolean; download?: boolean; restart?: boolean }) { + if (buttons.source !== undefined) { + this.props.tweakDisplay = buttons.source ? '' : 'none'; + } + if (buttons.download !== undefined) { + this.props.downloadDisplay = buttons.download ? '' : 'none'; + } + if (buttons.restart !== undefined) { + this.props.restartDisplay = buttons.restart ? '' : 'none'; + } + this.render(); + } + + setSourceVisibility(visible: boolean) { + const { textarea } = this.options; + if (!textarea) { + return; + } + textarea.style.display = visible ? '' : 'none'; + } + + setFilename(filename: string) { + this.filename = filename; + this.render(); + } + + showDownloadDialog() { + // Trigger the download click handler to show the popup + if (this.props.downloadClick) { + this.props.downloadClick(); + } + } + manageTextareaVisibilityForAgents() { const { textarea } = this.options;