share dialog is back

This commit is contained in:
Rachel Powers
2024-04-06 21:15:32 -07:00
parent 568601418a
commit 5c7ff7c287
10 changed files with 262 additions and 57 deletions

View File

@@ -1,7 +1,14 @@
import { HTMLTemplateResult, html, css, CSSResultGroup } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { BaseElement, defaultCss } from "../components";
import "./nav.ts";
import "./nav";
import "./share";
import { ShareSessionDialog } from "./share";
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js';
// Set the base path to the folder you copied Shoelace's assets to
setBasePath('/shoelace');
import "@shoelace-style/shoelace/dist/components/split-panel/split-panel.js";
@@ -29,9 +36,9 @@ export class App extends BaseElement {
flex-grow: 1;
// z-index: auto;
}
.z-fix {
z-index: 900;
}
// .z-fix {
// z-index: 900;
// }
sl-split-panel {
height: 100%;
}
@@ -40,9 +47,12 @@ export class App extends BaseElement {
editorSettings: { fontSize: number; relativeLineNumbers: boolean };
get editor() {
return this.renderRoot.querySelector("ace-ic10") as IC10Editor;
}
@query('ace-ic10') accessor editor: IC10Editor;
@query('session-share-dialog') accessor shareDialog: ShareSessionDialog;
// get editor() {
// return this.renderRoot.querySelector("ace-ic10") as IC10Editor;
// }
vm!: VirtualMachine;
session!: Session;
@@ -57,16 +67,16 @@ export class App extends BaseElement {
protected createRenderRoot(): HTMLElement | DocumentFragment {
const root = super.createRenderRoot();
root.addEventListener('app-share-session', this._handleShare);
root.addEventListener('app-open-file', this._handleOpenFile);
root.addEventListener('app-save-as', this._handleSaveAs);
root.addEventListener('app-share-session', this._handleShare.bind(this));
root.addEventListener('app-open-file', this._handleOpenFile.bind(this));
root.addEventListener('app-save-as', this._handleSaveAs.bind(this));
return root;
}
protected render(): HTMLTemplateResult {
return html`
<div class="app-container">
<app-nav class="z-fix"></app-nav>
<app-nav></app-nav>
<div class="app-body">
<sl-split-panel
style="--min: 20em; --max: calc(100% - 20em);"
@@ -74,10 +84,11 @@ export class App extends BaseElement {
snap="512px 50%"
snap-threshold="15"
>
<ace-ic10 slot="start"></ace-ic10>
<ace-ic10 slot="start" style=""></ace-ic10>
<div slot="end">Controls</div>
</sl-split-panel>
</div>
<session-share-dialog></session-share-dialog>
</div>
`;
}
@@ -87,6 +98,8 @@ export class App extends BaseElement {
_handleShare(_e: Event) {
// TODO:
this.shareDialog.link = window.location.href;
this.shareDialog.show();
}
_handleSaveAs(_e: Event) {

View File

@@ -1,4 +1,5 @@
import { App } from "./app";
import { Nav } from "./nav";
import { ShareSessionDialog } from "./share";
import "./icons";
export { App, Nav }
export { App, Nav, ShareSessionDialog }

View File

@@ -1,6 +1,8 @@
import { HTMLTemplateResult, html, css } from "lit";
import { customElement, property } from "lit/decorators.js";
import { BaseElement, defaultCss } from "../components";
import '@shoelace-style/shoelace/dist/components/icon/icon.js';
import "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js";
import "@shoelace-style/shoelace/dist/components/menu/menu.js";
import "@shoelace-style/shoelace/dist/components/divider/divider.js";
@@ -79,6 +81,7 @@ export class Nav extends BaseElement {
position: relative;
top: 50%;
transform: translateY(-50%);
z-index: 100;
}
nav {
border-bottom: 1px solid rgb(108, 117, 125);
@@ -101,7 +104,7 @@ export class Nav extends BaseElement {
label="Main Menu"
></sl-icon-button>
<sl-menu class="menu" @sl-select=${this._menuClickHandler}>
<sl-menu class="menu" @sl-select=${this._menuClickHandler} style="z-index: 10">
<sl-menu-item value="share">Share</sl-menu-item>
<sl-menu-item value="openFile">Open File</sl-menu-item>
<sl-menu-item value="saveAs">Save As</sl-menu-item>
@@ -180,10 +183,10 @@ export class Nav extends BaseElement {
this.dispatchEvent(new CustomEvent("app-save-as", { bubbles: true }));
break;
case "editorSettings":
window.Editor?.settingDialog.show();
window.Editor.settingDialog.show();
break;
case "keyboardShortcuts":
// TODO: bind
window.Editor.kbShortcuts.show();
break;
default:
console.log("Unknown main menu item", item.value);

49
www/src/js/app/share.ts Normal file
View File

@@ -0,0 +1,49 @@
import { HTMLTemplateResult, html, css } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { BaseElement, defaultCss } from "../components";
import "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
import "@shoelace-style/shoelace/dist/components/input/input.js";
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
import "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js";
import "@shoelace-style/shoelace/dist/components/copy-button/copy-button.js";
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
@customElement("session-share-dialog")
export class ShareSessionDialog extends BaseElement {
@query(".dialog") accessor dialog: SlDialog;
@query(".input") accessor input: SlInput;
@property({ type: String }) accessor link: string;
constructor() {
super();
}
protected render() {
return html`
<sl-dialog label="Share This Code" class="dialog" style="--header-spacing: 0.75em;">
<sl-input class="input" id="session-link-input" value="${this.link}">
<sl-icon name="link-45deg" slot="prefix"></sl-icon>
<sl-copy-button from="session-link-input.value" slot="suffix">
<sl-icon slot="copy-icon" name="clipboard"></sl-icon>
<sl-icon slot="success-icon" name="clipboard-check"></sl-icon>
<sl-icon slot="error-icon" name="clipboard-x"></sl-icon>
</sl-copy-button>
</sl-input>
</sl-dialog>
`;
}
show() {
this.dialog.show();
}
hide() {
this.dialog.hide();
}
_handleCopyClick() {
this.input.value;
}
}

View File

@@ -21,6 +21,7 @@ export async function setupLspWorker() {
}
export import EditSession = ace.Ace.EditSession;
export import Editor = ace.Ace.Editor;
import { Range } from "ace-builds";
export { ace, TextMode, Range, AceLanguageClient }

View File

@@ -4,7 +4,6 @@ import { rules as highlightRules } from "./ic10_highlight_rules";
//Support function to create Ace mode
function createAceMode(modeName: string, highlighterObj: ace.Ace.HighlightRulesMap) {
(ace as any).define(modeName, ["require", "exports", "module"], function (require: any, exports: any, module: any) {
console.log(require);
var oop = require("ace/lib/oop");
var TextMode = require("ace/mode/text").Mode;
var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;

View File

@@ -1,5 +1,6 @@
import {
ace,
Editor,
EditSession,
Range,
AceLanguageClient,
@@ -14,7 +15,7 @@ import "@shoelace-style/shoelace/dist/components/button/button.js";
import "@shoelace-style/shoelace/dist/components/input/input.js";
import "@shoelace-style/shoelace/dist/components/radio-button/radio-button.js";
import "@shoelace-style/shoelace/dist/components/radio-group/radio-group.js";
import '@shoelace-style/shoelace/dist/components/switch/switch.js';
import "@shoelace-style/shoelace/dist/components/switch/switch.js";
import SlDialog from "@shoelace-style/shoelace/dist/components/dialog/dialog.js";
import SlRadioGroup from "@shoelace-style/shoelace/dist/components/radio-group/radio-group.js";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
@@ -28,8 +29,11 @@ declare global {
import { BaseElement, defaultCss } from "../components";
import { html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { Ref, createRef, ref } from "lit/directives/ref.js";
import { customElement, property, query } from "lit/decorators.js";
import { editorStyles } from "./styles";
import "./shortcuts-ui";
import { AceKeyboardShortcuts } from "./shortcuts-ui";
@customElement("ace-ic10")
export class IC10Editor extends BaseElement {
@@ -55,7 +59,7 @@ export class IC10Editor extends BaseElement {
editorDiv: HTMLElement;
editorContainerDiv: HTMLElement;
editorStatusbarDiv: HTMLElement;
editor: ace.Ace.Editor;
editor: Editor;
statusBar: any;
snippetManager: any;
observer: ResizeObserver;
@@ -67,9 +71,9 @@ export class IC10Editor extends BaseElement {
stylesAdded: string[];
tooltipObserver: MutationObserver;
get settingDialog() {
return this.shadowRoot?.querySelector('sl-dialog') as SlDialog
}
@query('.e-kb-shortcuts') accessor kbShortcuts: AceKeyboardShortcuts;
@query('.e-settings-dialog') accessor settingDialog: SlDialog;
constructor() {
super();
@@ -95,32 +99,53 @@ export class IC10Editor extends BaseElement {
const result = html`
<div
id="editorContainer"
style="height: 100%; width: 100%; position: relative;"
style="height: 100%; width: 100%; position: relative; z-index: auto;"
>
<div
id="editor"
style="position: absolute; top: 0; right: 0; bottom: 0; left: 0;"
<!-- style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 0; isolation: isolate;" -->
></div>
<div id="editorStatusbar"></div>
</div>
<sl-dialog label="Editor Settings" class="dialog-focus">
<sl-radio-group id="editorKeyboardRadio" label="Editor Keyboard Bindings" value=${this.settings.keyboard}>
<sl-dialog
label="Editor Settings"
class="dialog-focus e-settings-dialog"
>
<sl-radio-group
id="editorKeyboardRadio"
label="Editor Keyboard Bindings"
value=${this.settings.keyboard}
>
<sl-radio-button value="ace">Ace</sl-radio-button>
<sl-radio-button value="vim">Vim</sl-radio-button>
<sl-radio-button value="emacs">Emacs</sl-radio-button>
<sl-radio-button value="sublime">Sublime</sl-radio-button>
<sl-radio-button value="vscode">VS Code</sl-radio-button>
</sl-radio-group>
<sl-radio-group id="editorCursorRadio" label="Editor Cursor Style" value=${this.settings.cursor}>
<sl-radio-group
id="editorCursorRadio"
label="Editor Cursor Style"
value=${this.settings.cursor}
>
<sl-radio-button value="ace">Ace</sl-radio-button>
<sl-radio-button value="slim">Slim</sl-radio-button>
<sl-radio-button value="smooth">Smooth</sl-radio-button>
<sl-radio-button value="smooth slim">Smooth And Slim</sl-radio-button>
<sl-radio-button value="wide">Wide</sl-radio-button>
</sl-radio-group>
<sl-input id="editorFontSize" label="Font Size" type="number" value="${this.settings.fontSize}"></sl-input>
<sl-switch id="editorRelativeLineNumbers" ?checked=${this.settings.relativeLineNumbers}>Relative Line Numbers</sl-switch>
<sl-input
id="editorFontSize"
label="Font Size"
type="number"
value="${this.settings.fontSize}"
></sl-input>
<sl-switch
id="editorRelativeLineNumbers"
?checked=${this.settings.relativeLineNumbers}
>Relative Line Numbers</sl-switch
>
</sl-dialog>
<ace-kb-menu class="e-kb-shortcuts"></ace-kb-menu>
`;
return result;
}
@@ -242,6 +267,8 @@ export class IC10Editor extends BaseElement {
});
this.observer.observe(this.editorContainerDiv);
this.kbShortcuts.editor = this.editor;
this.kbShortcuts.requestUpdate();
this.initializeEditor();
}
@@ -324,37 +351,57 @@ export class IC10Editor extends BaseElement {
this.shadowRoot!.querySelector(".ace_scrollbar-h")!,
);
editor.commands.addCommands([{
name: "showSettingsMenu",
// description: "Show settings menu",
bindKey: { win: "Ctrl-,", mac: "Command-,"},
exec: (_editor: ace.Ace.Editor) => {
that.settingDialog.show();
editor.commands.addCommands([
{
name: "showSettingsMenu",
// description: "Show settings menu",
bindKey: { win: "Ctrl-,", mac: "Command-," },
exec: (_editor: Editor) => {
that.settingDialog.show();
},
},
}]);
{
name: "showKeyboardShortcuts",
bindKey: {
win: "Ctrl-Alt-h",
mac: "Command-Alt-h",
},
exec: (_editor: Editor) => {
that.kbShortcuts.show();
},
},
]);
this.updateEditorSettings();
const keyboardRadio = this.renderRoot.querySelector("#editorKeyboardRadio")! as SlRadioGroup;
const cursorRadio = this.renderRoot.querySelector("#editorCursorRadio")! as SlRadioGroup;
const fontSize = this.renderRoot.querySelector("#editorFontSize")! as SlInput;
const relativeLineNumbers = this.renderRoot.querySelector("#editorRelativeLineNumbers")! as SlSwitch;
const keyboardRadio = this.renderRoot.querySelector(
"#editorKeyboardRadio",
)! as SlRadioGroup;
const cursorRadio = this.renderRoot.querySelector(
"#editorCursorRadio",
)! as SlRadioGroup;
const fontSize = this.renderRoot.querySelector(
"#editorFontSize",
)! as SlInput;
const relativeLineNumbers = this.renderRoot.querySelector(
"#editorRelativeLineNumbers",
)! as SlSwitch;
keyboardRadio.addEventListener("sl-change", _e => {
keyboardRadio.addEventListener("sl-change", (_e) => {
that.settings.keyboard = keyboardRadio.value;
that.updateEditorSettings();
that.saveEditorSettings();
});
cursorRadio?.addEventListener("sl-change", _e => {
cursorRadio?.addEventListener("sl-change", (_e) => {
that.settings.cursor = cursorRadio.value;
that.updateEditorSettings();
that.saveEditorSettings();
});
fontSize?.addEventListener("sl-change", _e => {
that.settings.fontSize = parseInt(fontSize.value)
fontSize?.addEventListener("sl-change", (_e) => {
that.settings.fontSize = parseInt(fontSize.value);
that.updateEditorSettings();
that.saveEditorSettings();
});
relativeLineNumbers?.addEventListener("sl-change", _e => {
relativeLineNumbers?.addEventListener("sl-change", (_e) => {
that.settings.relativeLineNumbers = relativeLineNumbers.checked;
that.updateEditorSettings();
that.saveEditorSettings();
@@ -505,14 +552,20 @@ export class IC10Editor extends BaseElement {
}
updateEditorSettings() {
if (this.settings.keyboard === 'ace') {
this.editor.setOption('keyboardHandler', null);
if (this.settings.keyboard === "ace") {
this.editor.setOption("keyboardHandler", null);
} else {
this.editor.setOption('keyboardHandler', `ace/keyboard/${this.settings.keyboard}`);
this.editor.setOption(
"keyboardHandler",
`ace/keyboard/${this.settings.keyboard}`,
);
}
this.editor.setOption('cursorStyle', this.settings.cursor as any);
this.editor.setOption('fontSize', this.settings.fontSize);
this.editor.setOption('relativeLineNumbers', this.settings.relativeLineNumbers);
this.editor.setOption("cursorStyle", this.settings.cursor as any);
this.editor.setOption("fontSize", this.settings.fontSize);
this.editor.setOption(
"relativeLineNumbers",
this.settings.relativeLineNumbers,
);
}
destroySession(session_id: number) {

View File

@@ -0,0 +1,78 @@
import { BaseElement, defaultCss } from "../components";
import { html, css, PropertyValueMap } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { ace, Editor } from "./ace";
import "@shoelace-style/shoelace/dist/components/drawer/drawer.js";
import { SlDrawer } from "@shoelace-style/shoelace";
import { Ref, createRef, ref } from "lit/directives/ref.js";
@customElement("ace-kb-menu")
export class AceKeyboardShortcuts extends BaseElement {
static styles = [
defaultCss,
css`
.command {
color: #c678dd;
font-weight: normal;
}
.entry:hover {
background-color: var(--sl-color-neutral-100);
transition: all 0.3s;
}
.key {
color: var(--sl-color-neutral-1000);
font-weight: bold;
}
`,
];
editor?: Editor;
@query('.drawer') accessor drawer: SlDrawer;
constructor() {
super();
}
// protected shouldUpdate(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): boolean {
// return true;
// }
protected async firstUpdated() {
if (!ace.require("ace/ext/menu_tools/get_editor_keyboard_shortcuts")) {
await import("ace-builds/src-noconflict/ext-keybinding_menu");
}
}
protected render() {
var kbs: any[] = [];
if (this.editor) {
const getEditorKeybordShortcuts = ace.require(
"ace/ext/menu_tools/get_editor_keyboard_shortcuts",
).getEditorKeybordShortcuts;
kbs = getEditorKeybordShortcuts(this.editor);
}
return html`
<sl-drawer label="Editor Keyboard Shortcuts" class="drawer">
<div>
${kbs.map(
(kb: any) =>
html`<div class="entry">
<span class="command">${kb.command}</span> :
<span class="key">${kb.key}</span>
</div>`,
)}
</div>
</sl-drawer>
`;
}
show() {
this.drawer.show();
}
hide() {
this.drawer.hide();
}
}

View File

@@ -8,7 +8,7 @@ export const editorStyles = css`
#editor {
// border: 1px solid;
// border-radius: 4px;
@apply --ace-widget-editor;
// @apply --ace-widget-editor;
}
#editorStatusbar {
z-index: 9 !important;