var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _PlayPen_instances, _PlayPen_env, _PlayPen_template, _PlayPen_appendPreviewError, _PlayPen_clearPreviewErrors, _PlayPen_onShare, _PlayPen_save, _PlayPen_setName, _PlayPen_setSrc, _PlayPen_shareURL;
import { LitElement, css, html, unsafeCSS } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { appEntrypointFilename, compile, newTSEnv, setSource } from '../../../bundler/compiler.js';
import { link } from '../../../bundler/linker.js';
import clock from '../../../examples/clock.example.js';
import defaultExample from '../../../examples/default.example.js';
import helloBlocks from '../../../examples/hello-blocks.example.js';
import polls from '../../../examples/polls.example.js';
import progressBar from '../../../examples/progress-bar.example.js';
import { PenSave, loadPen, penToHash, savePen } from '../../../types/pen-save.js';
import penVars from './pen-vars.css';
import '../play-editor/play-editor.js';
import '../play-pen-footer.js';
import '../play-pen-header.js';
import '../play-preview-controls.js';
import '../play-preview.js';
import '../play-toast.js';
/**
 * A complete and standalone playground: an editor, a runtime and client, a
 * preview and toolbar. Accepts a slotted template.
 *
 * @slot - Optional template.
 */
let PlayPen = class PlayPen extends LitElement {
    constructor() {
        super(...arguments);
        _PlayPen_instances.add(this);
        /**
         * Allow loading and saving from LocalStorage. Do not enable for multiple
         * playgrounds on the same document.
         */
        this.allowStorage = false;
        /**
         * Allow loading and saving from URL hash. Loading from hash has precedence
         * over LocalStorage. Do not enable for multiple playgrounds on the same
         * document.
         */
        this.allowURL = false;
        this.srcByLabel = {
            Default: defaultExample,
            'Hello Blocks!': helloBlocks,
            'Progress Bar': progressBar,
            Clock: clock,
            Polls: polls
        };
        /** Execution preview widths. */
        this._previewWidth = 288;
        this._diagnostics = { previewErrs: [], tsErrs: [] };
        _PlayPen_env.set(this, newTSEnv()
        /** Program title. */ );
        /** Program title. */ this._name = '';
        _PlayPen_template.set(this, void 0);
    }
    connectedCallback() {
        super.connectedCallback();
        let pen;
        if (this.allowURL)
            pen = loadPen(globalThis.location);
        if (this.allowStorage)
            pen ?? (pen = loadPen(globalThis.localStorage));
        if (!pen) {
            __classPrivateFieldSet(this, _PlayPen_template, true, "f");
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, helloBlocks, false);
            return;
        }
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, pen.src, false);
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setName).call(this, pen.name, false);
    }
    render() {
        return html `<play-toast>URL copied to clipboard.</play-toast
      ><play-pen-header
        name=${this._name}
        .srcByLabel=${this.srcByLabel}
        url=${__classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_shareURL).call(this).toString()}
        @edit-name=${(ev) => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setName).call(this, ev.detail, true)}
        @edit-src=${(ev) => {
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, ev.detail, false);
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setName).call(this, '', false);
            this._editor.setSrc(ev.detail);
        }}
        @share=${__classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_onShare)}
      ></play-pen-header>
      <main>
        <play-editor
          .env=${__classPrivateFieldGet(this, _PlayPen_env, "f")}
          src=${ifDefined(this._src)}
          @edit=${(ev) => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, ev.detail, true)}
          @edit-template=${(ev) => {
            this.srcByLabel = { ...this.srcByLabel, ['Default']: ev.detail };
            if (!__classPrivateFieldGet(this, _PlayPen_template, "f"))
                return;
            // If no source was restored, use the template.
            __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_setSrc).call(this, ev.detail, false);
            this._editor.setSrc(ev.detail);
        }}
          ><slot></slot
        ></play-editor>
        <div class="preview">
          <play-preview
            .bundle=${this._bundle}
            previewWidth=${this._previewWidth}
            scheme=${ifDefined(this._scheme)}
            @clear-errors=${() => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_clearPreviewErrors).call(this)}
            @error=${(ev) => __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_appendPreviewError).call(this, ev.detail)}
          ></play-preview>
          <play-preview-controls
            previewWidth=${this._previewWidth}
            scheme=${ifDefined(this._scheme)}
            @reset=${() => this._preview.reset()}
            @preview-width=${(ev) => (this._previewWidth = ev.detail)}
            @preview-scheme=${(ev) => (this._scheme = ev.detail)}
          ></play-preview-controls>
        </div>
      </main>
      <play-pen-footer
        .diagnostics=${this._diagnostics}
        @preview-width=${(ev) => (this._previewWidth = ev.detail)}
        @preview-scheme=${(ev) => (this._scheme = ev.detail)}
        @open-line=${(ev) => this._editor.openLine(ev.detail.line, ev.detail.char)}
      ></play-pen-footer>`;
    }
};
_PlayPen_env = new WeakMap();
_PlayPen_template = new WeakMap();
_PlayPen_instances = new WeakSet();
_PlayPen_appendPreviewError = function _PlayPen_appendPreviewError(err) {
    this._diagnostics = {
        ...this._diagnostics,
        previewErrs: [...this._diagnostics.previewErrs, err]
    };
};
_PlayPen_clearPreviewErrors = function _PlayPen_clearPreviewErrors() {
    if (this._diagnostics)
        this._diagnostics.previewErrs.length = 0;
    this._diagnostics = { ...this._diagnostics };
};
_PlayPen_onShare = async function _PlayPen_onShare() {
    await navigator.clipboard.writeText(__classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_shareURL).call(this).toString());
    this._toast.open();
};
_PlayPen_save = function _PlayPen_save() {
    savePen(this.allowURL ? globalThis.location : undefined, this.allowStorage ? globalThis.localStorage : undefined, PenSave(this._name, this._src ?? ''));
};
_PlayPen_setName = function _PlayPen_setName(name, save) {
    this._name = name;
    if (save)
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_save).call(this);
};
_PlayPen_setSrc = function _PlayPen_setSrc(src, save) {
    this._src = src;
    setSource(__classPrivateFieldGet(this, _PlayPen_env, "f"), src);
    __classPrivateFieldGet(this, _PlayPen_env, "f").updateFile(appEntrypointFilename, src || ' '); // empty strings trigger file deletion!
    this._diagnostics = {
        ...this._diagnostics,
        tsErrs: __classPrivateFieldGet(this, _PlayPen_env, "f").languageService.getSemanticDiagnostics(appEntrypointFilename)
    };
    // Skip blank source.
    if (!/^\s*$/.test(src))
        this._bundle = link(compile(__classPrivateFieldGet(this, _PlayPen_env, "f")));
    if (save)
        __classPrivateFieldGet(this, _PlayPen_instances, "m", _PlayPen_save).call(this);
};
_PlayPen_shareURL = function _PlayPen_shareURL() {
    const url = new URL(globalThis.location.toString());
    url.hash = penToHash(PenSave(this._name, this._src ?? ''));
    return url;
};
PlayPen.styles = css `
    ${unsafeCSS(penVars)}

    :host {
      /* Light mode. */
      color: var(--color-foreground);
      background-color: var(--color-background);

      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;

      /* Dark and light schemes are supported. */
      color-scheme: dark light;
    }

    play-editor {
      width: 100%;
      flex-grow: 1;
      flex-shrink: 1;
    }

    .preview {
      flex-shrink: 0;
      display: flex;
      flex-direction: column;
      row-gap: 8px;
    }

    main {
      column-gap: 16px;
      display: flex;
      flex-direction: row;
      overflow: clip;
      padding-right: 16px;
      padding-left: 16px;
      row-gap: 16px;
      height: 100%;
      background-color: var(--color-background);
      z-index: var(--z-base);
    }

    /* Makes dropdowns appear over other content */
    play-pen-header,
    play-pen-footer {
      z-index: var(--z-menu);
    }
  `;
__decorate([
    property({ attribute: 'allow-storage', type: Boolean })
], PlayPen.prototype, "allowStorage", void 0);
__decorate([
    property({ attribute: 'allow-url', type: Boolean })
], PlayPen.prototype, "allowURL", void 0);
__decorate([
    property({ attribute: false })
], PlayPen.prototype, "srcByLabel", void 0);
__decorate([
    state()
], PlayPen.prototype, "_bundle", void 0);
__decorate([
    state()
], PlayPen.prototype, "_previewWidth", void 0);
__decorate([
    state()
], PlayPen.prototype, "_diagnostics", void 0);
__decorate([
    query('play-editor')
], PlayPen.prototype, "_editor", void 0);
__decorate([
    query('play-preview')
], PlayPen.prototype, "_preview", void 0);
__decorate([
    query('play-toast')
], PlayPen.prototype, "_toast", void 0);
__decorate([
    state()
], PlayPen.prototype, "_name", void 0);
__decorate([
    state()
], PlayPen.prototype, "_scheme", void 0);
__decorate([
    state()
], PlayPen.prototype, "_src", void 0);
PlayPen = __decorate([
    customElement('play-pen')
], PlayPen);
export { PlayPen };
//# sourceMappingURL=play-pen.js.map