From c37ac22c486743bc929e9ce8cc98651fc63d2c69 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 18 Jun 2024 18:00:56 +0100 Subject: [PATCH] Add sample apps and update readme --- README.md | 1 + .../README.md | 244 ++--- .../client/src/content/fdc3-intent-view.ts | 82 ++ .../client/src/content/interop-intent-view.ts | 84 ++ .../client/src/content/settings-dialog.ts | 130 +-- .../client/src/platform/apps/apps.ts | 22 +- .../src/platform/layout/layout-override.ts | 24 +- .../client/src/platform/settings.ts | 13 +- .../client/src/provider.ts | 14 +- .../client/src/shapes/layout-shapes.ts | 6 +- .../client/src/shapes/setting-shapes.ts | 12 +- .../client/webpack.config.js | 28 + .../public/apps.json | 27 +- .../public/common/apps-contact.json | 179 ++++ .../public/common/apps-fdc3-2-0.json | 111 +++ .../public/common/apps-finance.json | 116 +++ .../public/common/apps-interop.json | 111 +++ .../public/common/apps-manager.json | 144 +++ .../public/common/apps.json | 169 +--- .../public/layouts/default.layout.fin.json | 339 ++++--- .../public/manifest.json | 3 +- .../platform/settings/settings-dialog.html | 2 +- .../public/settings.json | 88 +- .../public/style/core-web-styles.css | 857 +++++++++--------- .../public/views/fdc3-intent-view.html | 45 + .../public/views/interop-intent-view.html | 45 + how-to/web-interop/public/manifest.json | 3 +- 27 files changed, 1843 insertions(+), 1056 deletions(-) create mode 100644 how-to/web-interop-support-context-and-intents/client/src/content/fdc3-intent-view.ts create mode 100644 how-to/web-interop-support-context-and-intents/client/src/content/interop-intent-view.ts create mode 100644 how-to/web-interop-support-context-and-intents/public/common/apps-contact.json create mode 100644 how-to/web-interop-support-context-and-intents/public/common/apps-fdc3-2-0.json create mode 100644 how-to/web-interop-support-context-and-intents/public/common/apps-finance.json create mode 100644 how-to/web-interop-support-context-and-intents/public/common/apps-interop.json create mode 100644 how-to/web-interop-support-context-and-intents/public/common/apps-manager.json create mode 100644 how-to/web-interop-support-context-and-intents/public/views/fdc3-intent-view.html create mode 100644 how-to/web-interop-support-context-and-intents/public/views/interop-intent-view.html diff --git a/README.md b/README.md index 5c3cf01..f0247b9 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Want to learn how to use our Channel API, Interop API or FDC3 API inside of a de | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [Web Interop Basic](./how-to/web-interop-basic) | This basic how-to provides a way of configuring a a webpage with a number of framed applications that share contextual information. | [Example](https://built-on-openfin.github.io/web-starter/web/v18.0.0/web-interop-basic/platform/provider.html) | | [Web Interop](./how-to/web-interop) | This example how-to provides a way of configuring a a webpage with a number of framed applications using our layout system as well as a left hand panel so show that you can combine layout and iframe based content. | [Example](https://built-on-openfin.github.io/web-starter/web/v18.0.0/web-interop/platform/provider.html) | +| [Web Interop - Support Context and Intents](./how-to/web-interop-support-context-and-intents) | This is an example of a platform that has utilized the options of having a custom interop broker and a custom layout override to implement a platform that supports FDC3 as well as enhanced layout capabilities.. | [Example](https://built-on-openfin.github.io/web-starter/web/vnext/web-interop-support-context-and-intents/platform/provider.html) | ### Cloud Interop diff --git a/how-to/web-interop-support-context-and-intents/README.md b/how-to/web-interop-support-context-and-intents/README.md index d560935..8ea5493 100644 --- a/how-to/web-interop-support-context-and-intents/README.md +++ b/how-to/web-interop-support-context-and-intents/README.md @@ -1,23 +1,41 @@ -![OpenFin Web Interop Basic Example](../../assets/openfin-web-starter.png) +![OpenFin Support Context and Intents Example](../../assets/openfin-web-starter.png) > **_:information_source: OpenFin:_** [OpenFin](https://www.openfin.co/) libraries are a commercial product and this repo is for evaluation purposes. Use of the OpenFin npm packages is only granted pursuant to a license from OpenFin. Please [**contact us**](https://www.openfin.co/contact/) if you would like to request a developer evaluation key or to discuss a production license. -# OpenFin Web Interop - Support Context and Intents +# OpenFin - Support Context and Intents -This is a simple example that has a simple provider web page that acts as the main/index page. This page wires up the interop broker, provides an interop override and creates a layout using the [@openfin/core-web](https://www.npmjs.com/package/@openfin/core-web) library. +This is a richer example of an implementation of an interop broker override and layout override showing to support an fdc3 app directory with support for context and intents. -This page has a very simple layout which is made up of four iframes that inherit the interop settings they should use to connect to the web broker: +It uses the [@openfin/core-web](https://www.npmjs.com/package/@openfin/core-web) library. -- Local - An FDC3 View - This uses the FDC3 API to add a context listener and to broadcast a hardcoded context object. -- Local - An Interop View - This uses the OpenFin Interop API to add a context listener and to set context using a hardcoded context object. -- External - An FDC3 Tool used in our workspace platform starters that lets you experiment with context sharing using the FDC3 APIs. -- External - An Interop Tool used in our workspace platform starters that lets you experiment with context sharing using the OpenFin Interop API. +The platform supports multiple layouts and brings in a number of OpenFin sample applications that are used in our workspace platform starter examples. -It also has a left panel which is outside of the OpenFin Layout and represents a platform specific panel which simply uses fdc3 and logs what it receives. This iframe does not inherit interop settings (as it is not part of the OpenFin layout) and uses platform specific settings to connect. +The platform also supports: -[Live Launch Example](https://built-on-openfin.github.io/web-starter/web/v18.0.0/web-interop/platform/provider.html) +## FDC3 Related -![OpenFin Web Interop Example](./docs/web-interop.png) +- Reading multiple fdc3 app directories endpoints to create a list of applications +- The ability to launch an app using fdc3.open +- The ability to raise intents or raise intents by context +- The ability to find instances of applications and target them when raising an intent. +- The ability to share context across content. +- The ability to share context across platforms and machines using our [@openfin/cloud-interop](https://www.npmjs.com/package/@openfin/cloud-interop) library + +## Layout + +To show so much content we implemented a layout override so that we can: + +- Add and remove layouts +- Load a saved collection of layouts +- Switch the layout that is being viewed +- Finding the identity of a layout that contains a specific piece of content. +- Get the current snapshot of all the layouts and the currently focused layout. + +## Apps + +We bring in a number of apps from our workspace platform starter and dev tools. We also include 4 basic apps that support context and intents (using the fdc3 and Interop API). + +[Live Launch Example](https://built-on-openfin.github.io/web-starter/web/vnext/web-interop-support-context-and-intents/platform/provider.html) ## Getting Started @@ -53,143 +71,18 @@ There are a few things to note before trying to use @openfin/core-web: - You will need to copy the shared-worker.js file from the [@openfin/core-web](https://www.npmjs.com/package/@openfin/core-web) npm package to your public folder. We have created a [copy-core-web.js](./scripts/copy-core-web.js) script to do this and it is referenced in the build-client npm command. - You will need to copy the styles.css file for styling the layout from the [@openfin/core-web](https://www.npmjs.com/package/@openfin/core-web) npm package to your public folder. We have created a [copy-core-web.js](./scripts/copy-core-web.js) script to do this and it is referenced in the build-client npm command. -## How things are structured - -### Host - -The host is the entry point and it is the page that gets loaded into the Chrome/Edge/Safari/Firefox tab. - -It has a responsibility to create a connection providing a broker url and then initializing the broker providing an id (**this id will be needed by your content when it wishes to connect**). - -In the sample we use a [settings](./client/src/platform/settings.ts) file that reads settings from the [web manifest file](./public/manifest.json) but this has been removed from the snippet to simplify the code snippet. - -```javascript -import { connect } from "@openfin/core-web"; - -/** - * Initializes the OpenFin Web Broker connection. - */ -async function init(): Promise { - // Get the dom element that should host the layout - const layoutContainer = document.querySelector("#layout_container"); - - // Get the default layout - const layoutSnapshot = {...}; - - // Connect to the OpenFin Web Broker and pass the default layout. - // It is good practice to specify providerId even if content is explicitly specifying it for cases where - // this provider uses our layout system and content uses inheritance. currentContextGroup - // is useful for defaulting any client that uses inheritance through our layout system. - const fin = await connect({ options: { - brokerUrl: "http://localhost:6060/platform/iframe-broker.html", - interopConfig: { - providerId: "web-interop", - currentContextGroup: "green" - } - }, - connectionInheritance: "enabled", - platform: { layoutSnapshot } }); - - // You may now use the `fin` object to initialize the broker and the layout. - await fin.Interop.init("web-interop"); - // initialize the layout and pass it the dom element to bind to - await fin.Platform.Layout.init({ - container: layoutContainer - }); -} -``` - -The host html page [provider.html](./public/platform/provider.html) then: - -- imports this code and initializes it. -- brings in required content through the @openfin/core-web layout system. -- brings in the required css for the @openfin/core-web layout system. - -The host page initializes the OpenFin layout system and brings in a required css file that styles the layout system. This styles.css is brought in from the [@openfin/core-web](https://www.npmjs.com/package/@openfin/core-web) npm package. This style is copied to the public/style folder as core-web-styles.css using our [scripts/copy-core-web.js](./scripts/copy-core-web.js) script. It runs as part of the build process. - -### IFrame Broker - -This is the iframe that is referenced by the Host and Content Providers and it is how they communicate with each other. The iframe broker html page and the shared-webworker.js file have to reside on the same domain as the **host**. - -The [iframe broker html page](./public/platform/iframe-broker.html) uses the shared-webworker.js file that comes as part of the [@openfin/core-web](https://www.npmjs.com/package/@openfin/core-web) npm package. This script is copied to the public/js folder as shared-worker.bundle.js using our [scripts/copy-core-web.js](./scripts/copy-core-web.js) script. It runs as part of the build process. - -The iframe broker needs some initialization logic as well. - -```javascript -import { init as initBrokerConnection } from "@openfin/core-web/iframe-broker"; - -/** - * Initializes the OpenFin Web Broker connection. - * @returns A promise that resolves when the connection is established. - */ -async function init(): Promise { - // The shared worker is copied and renamed to the public/js directory from the @openfin/core-web package - // using the scripts/copy-shared-worker.js file that is called when npm run build is called. - return initBrokerConnection({ - sharedWorkerUrl: "http://localhost:6060/js/shared-worker.bundle.js" - }); -} -``` - -### Content - -Content refers to content that is framed within an iframe on the **host** html page. It establishes a connection to the **host** through the **iframe broker** via some initialization code. - -Some things to note about the content provider setup: - -- Content imports an init function from the [api.ts](./client/src/platform/api.ts) that creates the connection and assigns the window.fin and window.fdc3 APIs if they do not exist. -- You do not need to assign fdc3 or fin to the window object but we have done so for consistency with our workspace and container starter examples. -- The snippet below is the init function from the [api.ts](./client/src/platform/api.ts) file (although the settings function has been replaced with hard coded values for simplicity) that is imported and called. -- Content initializes the API and then runs code normally like it would inside of a workspace platform or container platform. -- the **finReady** event shown below is an example and doesn't exist in the OpenFin container as the API is injected into the document. We added **finReady** to have similar behavior to the **fdc3Ready** event that we also raise. - -```javascript -import { connect } from "@openfin/core-web"; - -/** - * Initializes the OpenFin Web Broker connection. - */ -export async function init(): Promise { - // Set window.fin to the `fin` object if needed. - if (window.fin === undefined) { - // Specify an interopConfig with a specific provider ID and a context group to initialize the `fin.me.interop` client on connection. - window.fin = await connect({ - options: { - brokerUrl: "http://localhost:6060/platform/iframe-broker.html", - interopConfig: { - providerId: "web-interop", - currentContextGroup: "green" - } - } - }); - console.log("Finished initializing the fin API."); - // Create and dispatch the finReady event - const event = new CustomEvent("finReady"); - window.dispatchEvent(event); - } - - if (window.fdc3 === undefined && window?.fin?.me.interop?.getFDC3Sync !== undefined) { - window.fdc3 = fin.me.interop.getFDC3Sync("2.0"); - console.log("Finished initializing the fdc3 API."); - // Create and dispatch the FDC3Ready event - const event = new CustomEvent("fdc3Ready"); - window.dispatchEvent(event); - } -} -``` - ## Settings -To make it easier to update settings we store them in the web [manifest.json](./public/manifest.json) inside of _custom_settings_. +To make it easier to update settings we include a definition of where to fetch settings in our web [manifest.json](./public/manifest.json) inside of _custom_settings_. ```json { - "name": "OpenFin Web Interop", - "short_name": "OpenFinWebInterop", + "name": "OpenFin - Support Context and Intents", + "short_name": "OpenFinSupportInteropContextAndIntents", "start_url": "./platform/provider.html", "display": "standalone", "background_color": "#fff", - "description": "An example showing a implementation of the OpenFin Web Interop Library.", + "description": "An example showing a implementation of the OpenFin Core Web Library to support context and intents as well as layouts.", "icons": [ { "src": "common/images/icon-blue.png", @@ -199,31 +92,60 @@ To make it easier to update settings we store them in the web [manifest.json](./ ], "related_applications": [], "custom_settings": { - "platform": { - "interop": { - "sharedWorkerUrl": "http://localhost:6060/js/shared-worker.bundle.js", - "brokerUrl": "http://localhost:6060/platform/iframe-broker.html", - "providerId": "web-interop", - "defaultContextGroup": "green" - }, - "layout": { - "panels": { - "left": { - "url": "http://localhost:6060/views/fdc3-panel.html", - "frameId": "left-panel" + "endpointProvider": { + "endpoints": [ + { + "id": "platform-settings", + "type": "fetch", + "options": { + "method": "GET", + "url": "http://localhost:6060/settings.json" } - }, - "layoutContainerId": "layout_container", - "defaultLayout": "http://localhost:6060/layouts/default.layout.fin.json" - } + } + ] } } } ``` -## A visual representation - -We've covered the key pieces. We have a host, one or more pieces of content and a common iframe broker html page that is used to tie them altogether. We also use the OpenFin Layout system to render a layout that is compatible with the OpenFin container. This layout means that content doesn't need to know specific details about the host and it can inherit them. We also demonstrate content outside of the layout system by having a left panel example. This left panel specifies connection details. +As you can see it will fetch a [settings.json](./public/settings.json) file. The shape of this file can be seen in [client/src/shapes/setting-shapes.ts](./client/src/shapes/setting-shapes.ts) is as follows: -This diagram is here to provide a rough visual guide to support the content above and the example: -![OpenFin Web Interop Rough Visual Guide](./docs/web-interop-visualization.png) +```typescript +/** + * Settings for the client + */ +export interface Settings { + /** + * Platform settings + */ + platform: { + interop: { + sharedWorkerUrl: string; + brokerUrl: string; + providerId: string; + defaultContextGroup?: string; + overrideOptions: PlatformInteropBrokerOptions; + }; + cloudInterop: { + connectParams: CloudInteropOverrideParams; + }; + layout: { + addLayoutId: string; + deleteLayoutId: string; + layoutContainerId: string; + layoutSelectorId: string; + defaultLayout: PlatformLayoutSnapshot | string; + }; + ui: { + logo: string; + title: string; + subTitle: string; + settingsResolver: SettingsResolverOptions; + }; + app: { + directory: string; + appResolver: AppResolverOptions; + }; + }; +} +``` diff --git a/how-to/web-interop-support-context-and-intents/client/src/content/fdc3-intent-view.ts b/how-to/web-interop-support-context-and-intents/client/src/content/fdc3-intent-view.ts new file mode 100644 index 0000000..ae7dbe2 --- /dev/null +++ b/how-to/web-interop-support-context-and-intents/client/src/content/fdc3-intent-view.ts @@ -0,0 +1,82 @@ +import type { Context } from "@finos/fdc3"; +import { init } from "./api"; + +window.addEventListener("DOMContentLoaded", async () => { + await init(true); + await initializeDOM(); +}); + +/** + * Raise an intent using the fdc3 API. + */ +async function raiseIntent(): Promise { + if (window.fin !== undefined) { + const context = { + type: "fdc3.contact", + name: "Andy Young", + id: { + email: "andy.young@example.com" + } + }; + const intent = "ViewContact"; + const intentResolver = await window.fdc3.raiseIntent(intent, context); + if (intentResolver !== undefined) { + console.log("Intent resolver received:", intentResolver); + } + } +} + +/** + * Adds an fdc3 intent listener to the window. + */ +async function addIntentListener(): Promise { + const intent = "ViewContact"; + if (window.fdc3) { + await window.fdc3.addIntentListener(intent, (ctx, metadata) => { + console.log(`Received Context For Intent: ${intent}`, ctx); + console.log(`Received Metadata With Intent: ${intent}`, metadata); + updateDOMElements(ctx); + }); + } else { + window.addEventListener("fdc3Ready", async () => { + if (window.fdc3) { + await window.fdc3.addIntentListener(intent, (ctx, metadata) => { + console.log(`Received Context For Intent: ${intent}`, ctx); + console.log(`Received Metadata With Intent: ${intent}`, metadata); + updateDOMElements(ctx); + }); + } + }); + } +} + +/** + * Updates the DOM elements with the provided context. + * @param context The context to update the DOM elements with. + */ +function updateDOMElements(context: Context): void { + const contextTypeSpan = document.querySelector("#contextType"); + const contextNameSpan = document.querySelector("#contextName"); + const contextBodyPre = document.querySelector("#contextBody"); + + if (contextTypeSpan !== null && contextNameSpan !== null && contextBodyPre !== null) { + contextTypeSpan.textContent = context.type; + contextNameSpan.textContent = context.name ?? "No name provided."; + contextBodyPre.textContent = JSON.stringify(context, null, 2); + } +} + +/** + * Initialize the DOM elements. + */ +async function initializeDOM(): Promise { + const raiseIntentButton = document.querySelector("#raiseIntent"); + + if (raiseIntentButton !== null) { + raiseIntentButton.addEventListener("click", async () => { + await raiseIntent(); + }); + } + + await addIntentListener(); +} diff --git a/how-to/web-interop-support-context-and-intents/client/src/content/interop-intent-view.ts b/how-to/web-interop-support-context-and-intents/client/src/content/interop-intent-view.ts new file mode 100644 index 0000000..762a9da --- /dev/null +++ b/how-to/web-interop-support-context-and-intents/client/src/content/interop-intent-view.ts @@ -0,0 +1,84 @@ +import type { Context } from "@finos/fdc3"; +import { init } from "./api"; + +window.addEventListener("DOMContentLoaded", async () => { + await init(true); + await initializeDOM(); +}); + +/** + * Raise an intent using the interop API. + */ +async function raiseIntent(): Promise { + if (window.fin !== undefined) { + const context = { + type: "fdc3.contact", + name: "Andy Young", + id: { + email: "andy.young@example.com" + } + }; + const intent = "ViewContact"; + const intentRequest = { + name: intent, + context + }; + const intentResolver = await fin.me.interop.fireIntent(intentRequest); + if (intentResolver !== undefined) { + console.log("Intent resolver received:", intentResolver); + } + } +} + +/** + * Adds an interop intent listener to the window. + */ +async function addIntentListener(): Promise { + const intent = "ViewContact"; + if (window.fin) { + await fin.me.interop.registerIntentHandler((passedIntent) => { + console.log(`Received Context For Intent: ${passedIntent.name}`, passedIntent.context); + updateDOMElements(passedIntent.context); + }, intent); + } else { + window.addEventListener("finReady", async () => { + if (window.fin) { + await fin.me.interop.registerIntentHandler((passedIntent) => { + console.log(`Received Context For Intent: ${passedIntent.name}`, passedIntent.context); + updateDOMElements(passedIntent.context); + }, intent); + } + }); + } +} + +/** + * Updates the DOM elements with the provided context. + * @param context The context to update the DOM elements with. + */ +function updateDOMElements(context: Context): void { + const contextTypeSpan = document.querySelector("#contextType"); + const contextNameSpan = document.querySelector("#contextName"); + const contextBodyPre = document.querySelector("#contextBody"); + + if (contextTypeSpan !== null && contextNameSpan !== null && contextBodyPre !== null) { + contextTypeSpan.textContent = context.type; + contextNameSpan.textContent = context.name ?? "No name provided."; + contextBodyPre.textContent = JSON.stringify(context, null, 2); + } +} + +/** + * Initialize the DOM elements. + */ +async function initializeDOM(): Promise { + const raiseIntentButton = document.querySelector("#raiseIntent"); + + if (raiseIntentButton !== null) { + raiseIntentButton.addEventListener("click", async () => { + await raiseIntent(); + }); + } + + await addIntentListener(); +} diff --git a/how-to/web-interop-support-context-and-intents/client/src/content/settings-dialog.ts b/how-to/web-interop-support-context-and-intents/client/src/content/settings-dialog.ts index 964805b..6abb298 100644 --- a/how-to/web-interop-support-context-and-intents/client/src/content/settings-dialog.ts +++ b/how-to/web-interop-support-context-and-intents/client/src/content/settings-dialog.ts @@ -1,11 +1,11 @@ import { getSettings } from "../platform/settings"; window.addEventListener("DOMContentLoaded", async () => { - if (window.fdc3) { - await init(); + if (window.fdc3) { + await init(); } else { window.addEventListener("fdc3Ready", async () => { - await init(); + await init(); }); } }); @@ -14,73 +14,89 @@ window.addEventListener("DOMContentLoaded", async () => { * Initialize the settings. */ async function init(): Promise { - const settings = await getSettings(); - if (settings === undefined) { - console.error("Unable to run the example as we have been unable to load the web manifest and it's settings from the currently running html page. Please ensure that the web manifest is being served and that it contains the custom_settings section."); - return; - } + const settings = await getSettings(); + if (settings === undefined) { + console.error( + "Unable to run the example as we have been unable to load the web manifest and it's settings from the currently running html page. Please ensure that the web manifest is being served and that it contains the custom_settings section." + ); + return; + } - // platform settings - const title = document.querySelector("#title"); + // platform settings + const title = document.querySelector("#title"); const subTitle = document.querySelector("#subTitle"); const logo = document.querySelector("#logo"); - // cloud settings - const userId = document.querySelector("#userId"); + // cloud settings + const userId = document.querySelector("#userId"); const password = document.querySelector("#password"); const platformId = document.querySelector("#platformId"); - const cloudUrl = document.querySelector("#cloudUrl"); + const cloudUrl = document.querySelector("#cloudUrl"); const sourceId = document.querySelector("#sourceId"); - const sourceDisplayName = document.querySelector("#sourceDisplayName"); + const sourceDisplayName = document.querySelector("#sourceDisplayName"); - const saveButton = document.querySelector("#save"); - const resetButton = document.querySelector("#reset"); - const cancelButton = document.querySelector("#cancel"); + const saveButton = document.querySelector("#save"); + const resetButton = document.querySelector("#reset"); + const cancelButton = document.querySelector("#cancel"); - // assign returned settings to the input fields - if(title === null || subTitle === null || logo === null || - userId === null || password === null || platformId === null || - cloudUrl === null || sourceId === null || sourceDisplayName === null || - saveButton === null || resetButton === null || cancelButton === null) { - console.error("Unable to use settings as there are missing input fields/buttons."); - return; - } + // assign returned settings to the input fields + if ( + title === null || + subTitle === null || + logo === null || + userId === null || + password === null || + platformId === null || + cloudUrl === null || + sourceId === null || + sourceDisplayName === null || + saveButton === null || + resetButton === null || + cancelButton === null + ) { + console.error("Unable to use settings as there are missing input fields/buttons."); + return; + } - title.value = settings?.platform?.ui?.title; - subTitle.value = settings?.platform?.ui?.subTitle; - logo.value = settings?.platform?.ui?.logo; - userId.value = settings?.platform.cloudInterop?.connectParams?.userId; - password.value = settings?.platform.cloudInterop?.connectParams?.password; - platformId.value = settings?.platform.cloudInterop?.connectParams?.platformId; - cloudUrl.value = settings?.platform.cloudInterop?.connectParams?.url; - sourceId.value = settings?.platform.cloudInterop?.connectParams.sourceId ?? ""; - sourceDisplayName.value = settings?.platform.cloudInterop?.connectParams.sourceDisplayName ?? ""; + title.value = settings?.platform?.ui?.title; + subTitle.value = settings?.platform?.ui?.subTitle; + logo.value = settings?.platform?.ui?.logo; + userId.value = settings?.platform.cloudInterop?.connectParams?.userId; + password.value = settings?.platform.cloudInterop?.connectParams?.password; + platformId.value = settings?.platform.cloudInterop?.connectParams?.platformId; + cloudUrl.value = settings?.platform.cloudInterop?.connectParams?.url; + sourceId.value = settings?.platform.cloudInterop?.connectParams.sourceId ?? ""; + sourceDisplayName.value = settings?.platform.cloudInterop?.connectParams.sourceDisplayName ?? ""; - const channel = "platform/settings/dialog"; - const appChannel = await window.fdc3.getOrCreateChannel(channel); + const channel = "platform/settings/dialog"; + const appChannel = await window.fdc3.getOrCreateChannel(channel); - saveButton.addEventListener("click", async () => { - settings.platform.ui.title = title.value; - settings.platform.ui.subTitle = subTitle.value; - settings.platform.ui.logo = logo.value; - settings.platform.cloudInterop.connectParams.userId = userId.value; - settings.platform.cloudInterop.connectParams.password = password.value; - settings.platform.cloudInterop.connectParams.platformId = platformId.value; - settings.platform.cloudInterop.connectParams.url = cloudUrl.value; - settings.platform.cloudInterop.connectParams.sourceId = sourceId.value; - settings.platform.cloudInterop.connectParams.sourceDisplayName = sourceDisplayName.value; + saveButton.addEventListener("click", async () => { + settings.platform.ui.title = title.value; + settings.platform.ui.subTitle = subTitle.value; + settings.platform.ui.logo = logo.value; + settings.platform.cloudInterop.connectParams.userId = userId.value; + settings.platform.cloudInterop.connectParams.password = password.value; + settings.platform.cloudInterop.connectParams.platformId = platformId.value; + settings.platform.cloudInterop.connectParams.url = cloudUrl.value; + settings.platform.cloudInterop.connectParams.sourceId = sourceId.value; + settings.platform.cloudInterop.connectParams.sourceDisplayName = sourceDisplayName.value; - // an example of using an app channel. - await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "save-reload" }, settings }); - }); + // an example of using an app channel. + await appChannel.broadcast({ + type: "platform.settings.dialog.action", + id: { action: "save-reload" }, + settings + }); + }); - resetButton.addEventListener("click", async () => { - // an example of using an app channel. - await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "reset-reload" } }); - }); + resetButton.addEventListener("click", async () => { + // an example of using an app channel. + await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "reset-reload" } }); + }); - cancelButton.addEventListener("click", async () => { - // an example of using an app channel. - await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "close" } }); - }); + cancelButton.addEventListener("click", async () => { + // an example of using an app channel. + await appChannel.broadcast({ type: "platform.settings.dialog.action", id: { action: "close" } }); + }); } diff --git a/how-to/web-interop-support-context-and-intents/client/src/platform/apps/apps.ts b/how-to/web-interop-support-context-and-intents/client/src/platform/apps/apps.ts index d9cf93e..bb2af29 100644 --- a/how-to/web-interop-support-context-and-intents/client/src/platform/apps/apps.ts +++ b/how-to/web-interop-support-context-and-intents/client/src/platform/apps/apps.ts @@ -28,20 +28,14 @@ export async function getApps(): Promise { } const settings = await getSettings(); if (Array.isArray(settings?.platform?.app?.directory)) { - // Fetch data from all URLs concurrently - const responses = await Promise.all( - settings.platform.app.directory.map(async (url) => fetch(url)) - ); - // Parse the JSON from all responses - const appDirectories = await Promise.all( - responses.map(async (response) => response.json()) - ); - // Combine all applications into a single array - cachedApps = appDirectories.flatMap( - (appDirectory) => appDirectory.applications - ); - return cachedApps; - } + // Fetch data from all URLs concurrently + const responses = await Promise.all(settings.platform.app.directory.map(async (url) => fetch(url))); + // Parse the JSON from all responses + const appDirectories = await Promise.all(responses.map(async (response) => response.json())); + // Combine all applications into a single array + cachedApps = appDirectories.flatMap((appDirectory) => appDirectory.applications); + return cachedApps; + } cachedApps = []; return cachedApps; } diff --git a/how-to/web-interop-support-context-and-intents/client/src/platform/layout/layout-override.ts b/how-to/web-interop-support-context-and-intents/client/src/platform/layout/layout-override.ts index 0a75280..4600324 100644 --- a/how-to/web-interop-support-context-and-intents/client/src/platform/layout/layout-override.ts +++ b/how-to/web-interop-support-context-and-intents/client/src/platform/layout/layout-override.ts @@ -62,7 +62,7 @@ export function makeOverride( layoutSelected: this._selectedLayout }; for (const layout of this._layoutMapArray) { - if(layout.layoutTitle !== undefined) { + if (layout.layoutTitle !== undefined) { platformLayoutSnapshot.layoutTitles[layout.layoutName] = layout.layoutTitle; } } @@ -78,8 +78,10 @@ export function makeOverride( if (this._layoutContainer !== null && this._layoutContainer !== undefined) { const platformLayoutSnapshot = snapshot as PlatformLayoutSnapshot; for (const [key, value] of Object.entries(snapshot.layouts)) { - const layoutTitle = platformLayoutSnapshot?.layoutTitles === undefined - ? undefined : platformLayoutSnapshot.layoutTitles[key]; + const layoutTitle = + platformLayoutSnapshot?.layoutTitles === undefined + ? undefined + : platformLayoutSnapshot.layoutTitles[key]; this._layoutMapArray.push({ layoutName: key, layoutTitle, @@ -93,8 +95,13 @@ export function makeOverride( for (const entry of entries) { entryInstance++; const layoutName = entry[0]; - await this.createLayout(layoutName, entry[1], entryInstance, entries.length, - platformLayoutSnapshot.layoutSelected); + await this.createLayout( + layoutName, + entry[1], + entryInstance, + entries.length, + platformLayoutSnapshot.layoutSelected + ); } }, 1000); console.log("[Apply Layout] Layouts loaded"); @@ -217,8 +224,11 @@ export function makeOverride( this._layoutContainer?.append(container); if (entry === length) { this.bindLayoutSelector(selectedLayout ?? layoutName); - await this.showLayout({ layoutName: selectedLayout ?? layoutName, - uuid: fin.me.uuid, name: fin.me.name }); + await this.showLayout({ + layoutName: selectedLayout ?? layoutName, + uuid: fin.me.uuid, + name: fin.me.name + }); } // Finally, call the Layout.create() function to apply the snapshot layout to the div we just created. await fin.Platform.Layout.create({ layoutName, layout, container }); diff --git a/how-to/web-interop-support-context-and-intents/client/src/platform/settings.ts b/how-to/web-interop-support-context-and-intents/client/src/platform/settings.ts index 69adc69..636705a 100644 --- a/how-to/web-interop-support-context-and-intents/client/src/platform/settings.ts +++ b/how-to/web-interop-support-context-and-intents/client/src/platform/settings.ts @@ -17,9 +17,16 @@ export async function getSettings(): Promise { ); return; } - const settingsEndpoint = settings.endpointProvider.endpoints.find((endpoint) => endpoint.id === "platform-settings"); + const settingsEndpoint = settings.endpointProvider.endpoints.find( + (endpoint) => endpoint.id === "platform-settings" + ); - if(settingsEndpoint === undefined || settingsEndpoint.type !== "fetch" || settingsEndpoint.options.method !== "GET" || settingsEndpoint.options.url === undefined) { + if ( + settingsEndpoint === undefined || + settingsEndpoint.type !== "fetch" || + settingsEndpoint.options.method !== "GET" || + settingsEndpoint.options.url === undefined + ) { console.error( "Unable to run the example as settings are required and we fetch them from the endpoint defined with the id: 'platform-settings' in the manifest. It needs to be of type fetch, performing a GET and it must have a url defined." ); @@ -103,5 +110,5 @@ function getSavedSettingsId(): string { const env = urlParams.get("env"); const settingsKey = env ? `${env}-settings` : "settings"; - return settingsKey; + return settingsKey; } diff --git a/how-to/web-interop-support-context-and-intents/client/src/provider.ts b/how-to/web-interop-support-context-and-intents/client/src/provider.ts index ac169f4..dace5fa 100644 --- a/how-to/web-interop-support-context-and-intents/client/src/provider.ts +++ b/how-to/web-interop-support-context-and-intents/client/src/provider.ts @@ -1,3 +1,4 @@ +import { cloudInteropOverride } from "@openfin/cloud-interop"; import type { OpenFin } from "@openfin/core"; import { connect } from "@openfin/core-web"; import { AppResolverHelper } from "./platform/apps/app-resolver-helper"; @@ -7,7 +8,6 @@ import { clearSettings, getDefaultLayout, getSettings, saveSettings } from "./pl import type { PlatformLayoutSnapshot } from "./shapes/layout-shapes"; import type { Settings } from "./shapes/setting-shapes"; import { sanitizeString } from "./utils"; -import { cloudInteropOverride } from "@openfin/cloud-interop"; /** * Attach listeners to elements. @@ -43,7 +43,7 @@ async function attachListeners(fin: OpenFin.Fin): Promise): Promise("#title"); const subTitle = document.querySelector("#subTitle"); const logo = document.querySelector("#logo"); - if(title === null || subTitle === null || logo === null || settings === undefined) { - console.error("Unable to use settings as there are missing input fields/buttons or settings have not been provided."); + if (title === null || subTitle === null || logo === null || settings === undefined) { + console.error( + "Unable to use settings as there are missing input fields/buttons or settings have not been provided." + ); return; } const documentTitle = sanitizeString(settings?.platform?.ui?.title ?? ""); @@ -107,7 +109,7 @@ function updateDOM(settings: Settings | undefined): void { const documentIcon = sanitizeString(settings?.platform?.ui?.logo ?? ""); logo.src = documentIcon; const fav = document.querySelector("#favicon"); - if(fav !== null && documentIcon !== "") { + if (fav !== null && documentIcon !== "") { fav.href = documentIcon; } } diff --git a/how-to/web-interop-support-context-and-intents/client/src/shapes/layout-shapes.ts b/how-to/web-interop-support-context-and-intents/client/src/shapes/layout-shapes.ts index d2d5765..b92dc18 100644 --- a/how-to/web-interop-support-context-and-intents/client/src/shapes/layout-shapes.ts +++ b/how-to/web-interop-support-context-and-intents/client/src/shapes/layout-shapes.ts @@ -10,8 +10,10 @@ export type LayoutManagerConstructor = OpenFin.LayoutManagerConstructorPlatform
- +
diff --git a/how-to/web-interop-support-context-and-intents/public/settings.json b/how-to/web-interop-support-context-and-intents/public/settings.json index 2ef4ed2..9546844 100644 --- a/how-to/web-interop-support-context-and-intents/public/settings.json +++ b/how-to/web-interop-support-context-and-intents/public/settings.json @@ -1,27 +1,27 @@ { - "platform": { - "ui": { - "logo": "http://localhost:6060/common/images/icon-blue.png", - "title": "OpenFin - Support Context and Intents", - "subTitle": "Demonstrate how OpenFin's FDC3 Context and Intents support can be utilized and combined with OpenFin's Layout support.", - "settingsResolver": { - "url": "http://localhost:6060/platform/settings/settings-dialog.html" - } - }, - "interop": { - "sharedWorkerUrl": "http://localhost:6060/js/shared-worker.bundle.js", - "brokerUrl": "http://localhost:6060/platform/iframe-broker.html", - "providerId": "support-context-and-intents", - "defaultContextGroup": "green", - "overrideOptions": { - "intentResolver": { - "url": "http://localhost:6060/platform/intents/instance-picker.html", - "title": "Intent Resolver" - } - } - }, - "cloudInterop": { - "connectParams": { + "platform": { + "ui": { + "logo": "http://localhost:6060/common/images/icon-blue.png", + "title": "OpenFin - Support Context and Intents", + "subTitle": "Demonstrate how OpenFin's FDC3 Context and Intents support can be utilized and combined with OpenFin's Layout support.", + "settingsResolver": { + "url": "http://localhost:6060/platform/settings/settings-dialog.html" + } + }, + "interop": { + "sharedWorkerUrl": "http://localhost:6060/js/shared-worker.bundle.js", + "brokerUrl": "http://localhost:6060/platform/iframe-broker.html", + "providerId": "support-context-and-intents", + "defaultContextGroup": "green", + "overrideOptions": { + "intentResolver": { + "url": "http://localhost:6060/platform/intents/instance-picker.html", + "title": "Intent Resolver" + } + } + }, + "cloudInterop": { + "connectParams": { "userId": "", "password": "", "platformId": "", @@ -29,20 +29,28 @@ "sourceId": "cloud-interop-contents-and-intents", "sourceDisplayName": "Cloud Interop Basic Example" } - }, - "layout": { - "addLayoutId": "add-layout", - "deleteLayoutId": "delete-layout", - "layoutContainerId": "layout_container", - "layoutSelectorId": "layout-selector", - "defaultLayout": "http://localhost:6060/layouts/default.layout.fin.json" - }, - "app": { - "directory": ["http://localhost:6060/apps.json", "http://localhost:6060/common/apps.json"], - "appResolver": { - "url": "http://localhost:6060/platform/apps/app-picker.html", - "title": "App Resolver" - } - } - } -} \ No newline at end of file + }, + "layout": { + "addLayoutId": "add-layout", + "deleteLayoutId": "delete-layout", + "layoutContainerId": "layout_container", + "layoutSelectorId": "layout-selector", + "defaultLayout": "http://localhost:6060/layouts/default.layout.fin.json" + }, + "app": { + "directory": [ + "http://localhost:6060/apps.json", + "http://localhost:6060/common/apps.json", + "http://localhost:6060/common/apps-fdc3-2-0.json", + "http://localhost:6060/common/apps-interop.json", + "http://localhost:6060/common/apps-contact.json", + "http://localhost:6060/common/apps-manager.json", + "http://localhost:6060/common/apps-finance.json" + ], + "appResolver": { + "url": "http://localhost:6060/platform/apps/app-picker.html", + "title": "App Resolver" + } + } + } +} diff --git a/how-to/web-interop-support-context-and-intents/public/style/core-web-styles.css b/how-to/web-interop-support-context-and-intents/public/style/core-web-styles.css index d5bf42b..b760446 100644 --- a/how-to/web-interop-support-context-and-intents/public/style/core-web-styles.css +++ b/how-to/web-interop-support-context-and-intents/public/style/core-web-styles.css @@ -1,722 +1,741 @@ .lm_root { - position: relative; + position: relative; } .lm_row > .lm_item { - float: left; + float: left; } .lm_content { - overflow: hidden; - position: relative; + overflow: hidden; + position: relative; } .lm_dragging, .lm_dragging * { - cursor: move !important; - -webkit-user-select: none; - user-select: none; + cursor: move !important; + -webkit-user-select: none; + user-select: none; } .lm_maximised { - position: absolute; - top: 0; - left: 0; - z-index: 40; + position: absolute; + top: 0; + left: 0; + z-index: 40; } .lm_maximise_placeholder { - display: none; + display: none; } .lm_splitter { - position: relative; - z-index: 2; - touch-action: none; + position: relative; + z-index: 2; + touch-action: none; } .lm_splitter.lm_vertical .lm_drag_handle { - width: 100%; - position: absolute; - cursor: ns-resize; - touch-action: none; - -webkit-user-select: none; - user-select: none; + width: 100%; + position: absolute; + cursor: ns-resize; + touch-action: none; + -webkit-user-select: none; + user-select: none; } .lm_splitter.lm_horizontal { - float: left; - height: 100%; + float: left; + height: 100%; } .lm_splitter.lm_horizontal .lm_drag_handle { - height: 100%; - position: absolute; - cursor: ew-resize; - touch-action: none; - -webkit-user-select: none; - user-select: none; + height: 100%; + position: absolute; + cursor: ew-resize; + touch-action: none; + -webkit-user-select: none; + user-select: none; } .lm_header { - overflow: visible; - position: relative; - z-index: 1; - -webkit-user-select: none; - user-select: none; + overflow: visible; + position: relative; + z-index: 1; + -webkit-user-select: none; + user-select: none; } -.lm_header [class^=lm_] { - box-sizing: content-box !important; +.lm_header [class^='lm_'] { + box-sizing: content-box !important; } .lm_header .lm_controls { - position: absolute; - right: 3px; - display: flex; + position: absolute; + right: 3px; + display: flex; } .lm_header .lm_controls > * { - cursor: pointer; - float: left; - width: 18px; - height: 18px; - text-align: center; + cursor: pointer; + float: left; + width: 18px; + height: 18px; + text-align: center; } .lm_header .lm_tabs { - position: absolute; - display: flex; + position: absolute; + display: flex; } .lm_header .lm_tab { - cursor: pointer; - float: left; - height: 14px; - margin-top: 1px; - padding: 0px 10px 5px; - padding-right: 25px; - position: relative; - touch-action: none; + cursor: pointer; + float: left; + height: 14px; + margin-top: 1px; + padding: 0px 10px 5px; + padding-right: 25px; + position: relative; + touch-action: none; } .lm_header .lm_tab i { - width: 2px; - height: 19px; - position: absolute; + width: 2px; + height: 19px; + position: absolute; } .lm_header .lm_tab i.lm_left { - top: 0; - left: -2px; + top: 0; + left: -2px; } .lm_header .lm_tab i.lm_right { - top: 0; - right: -2px; + top: 0; + right: -2px; } .lm_header .lm_tab .lm_title { - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; } .lm_header .lm_tab .lm_close_tab { - width: 14px; - height: 14px; - position: absolute; - top: 0; - right: 0; - text-align: center; + width: 14px; + height: 14px; + position: absolute; + top: 0; + right: 0; + text-align: center; } .lm_stack { - position: relative; + position: relative; } .lm_stack > .lm_items { - overflow: hidden; + overflow: hidden; } .lm_stack.lm_left > .lm_items { - position: absolute; - left: 20px; - top: 0; + position: absolute; + left: 20px; + top: 0; } .lm_stack.lm_right > .lm_items { - position: absolute; - right: 20px; - top: 0; + position: absolute; + right: 20px; + top: 0; } .lm_stack.lm_right > .lm_header { - position: absolute; - right: 0; - top: 0; + position: absolute; + right: 0; + top: 0; } .lm_stack.lm_bottom > .lm_items { - position: absolute; - bottom: 20px; + position: absolute; + bottom: 20px; } .lm_stack.lm_bottom > .lm_header { - position: absolute; - bottom: 0; + position: absolute; + bottom: 0; } .lm_left.lm_stack .lm_header, .lm_right.lm_stack .lm_header { - height: 100%; + height: 100%; } .lm_left.lm_dragProxy .lm_header, .lm_right.lm_dragProxy .lm_header, .lm_left.lm_dragProxy .lm_items, .lm_right.lm_dragProxy .lm_items { - float: left; + float: left; } .lm_left.lm_dragProxy .lm_header, .lm_right.lm_dragProxy .lm_header, .lm_left.lm_stack .lm_header, .lm_right.lm_stack .lm_header { - width: 20px; - vertical-align: top; + width: 20px; + vertical-align: top; } .lm_left.lm_dragProxy .lm_header .lm_tabs, .lm_right.lm_dragProxy .lm_header .lm_tabs, .lm_left.lm_stack .lm_header .lm_tabs, .lm_right.lm_stack .lm_header .lm_tabs { - transform-origin: left top; - top: 0; - width: 1000px; - /*hack*/ + transform-origin: left top; + top: 0; + width: 1000px; + /*hack*/ } .lm_left.lm_dragProxy .lm_header .lm_controls, .lm_right.lm_dragProxy .lm_header .lm_controls, .lm_left.lm_stack .lm_header .lm_controls, .lm_right.lm_stack .lm_header .lm_controls { - bottom: 0; - flex-flow: column; + bottom: 0; + flex-flow: column; } .lm_dragProxy.lm_left .lm_header .lm_tabs, .lm_stack.lm_left .lm_header .lm_tabs { - transform: rotate(-90deg) scaleX(-1); - left: 0; + transform: rotate(-90deg) scaleX(-1); + left: 0; } .lm_dragProxy.lm_left .lm_header .lm_tabs .lm_tab, .lm_stack.lm_left .lm_header .lm_tabs .lm_tab { - transform: scaleX(-1); - margin-top: 1px; + transform: scaleX(-1); + margin-top: 1px; } .lm_dragProxy.lm_left .lm_header .lm_tabdropdown_list, .lm_stack.lm_left .lm_header .lm_tabdropdown_list { - top: initial; - right: initial; - left: 20px; + top: initial; + right: initial; + left: 20px; } .lm_dragProxy.lm_right .lm_content { - float: left; + float: left; } .lm_dragProxy.lm_right .lm_header .lm_tabs, .lm_stack.lm_right .lm_header .lm_tabs { - transform: rotate(90deg) scaleX(1); - left: 100%; - margin-left: 0; + transform: rotate(90deg) scaleX(1); + left: 100%; + margin-left: 0; } .lm_dragProxy.lm_right .lm_header .lm_controls, .lm_stack.lm_right .lm_header .lm_controls { - left: 3px; + left: 3px; } .lm_dragProxy.lm_right .lm_header .lm_tabdropdown_list, .lm_stack.lm_right .lm_header .lm_tabdropdown_list { - top: initial; - right: 20px; + top: initial; + right: 20px; } .lm_dragProxy.lm_bottom .lm_header, .lm_stack.lm_bottom .lm_header { - width: 100%; + width: 100%; } .lm_dragProxy.lm_bottom .lm_header .lm_tab, .lm_stack.lm_bottom .lm_header .lm_tab { - margin-top: 0; - border-top: none; + margin-top: 0; + border-top: none; } .lm_dragProxy.lm_bottom .lm_header .lm_controls, .lm_stack.lm_bottom .lm_header .lm_controls { - top: 3px; + top: 3px; } .lm_dragProxy.lm_bottom .lm_header .lm_tabdropdown_list, .lm_stack.lm_bottom .lm_header .lm_tabdropdown_list { - top: initial; - bottom: 20px; + top: initial; + bottom: 20px; } .lm_drop_tab_placeholder { - float: left; - width: 100px; - visibility: hidden; + float: left; + width: 100px; + visibility: hidden; } .lm_header .lm_controls .lm_tabdropdown:before { - content: ''; - width: 0; - height: 0; - vertical-align: middle; - display: inline-block; - border-top: 5px dashed; - border-right: 5px solid transparent; - border-left: 5px solid transparent; - color: white; + content: ''; + width: 0; + height: 0; + vertical-align: middle; + display: inline-block; + border-top: 5px dashed; + border-right: 5px solid transparent; + border-left: 5px solid transparent; + color: white; } .lm_header .lm_tabdropdown_list { - position: absolute; - top: 20px; - right: 0; - z-index: 5; - overflow: hidden; + position: absolute; + top: 20px; + right: 0; + z-index: 5; + overflow: hidden; } .lm_header .lm_tabdropdown_list .lm_tab { - clear: both; - padding-right: 10px; - margin: 0; + clear: both; + padding-right: 10px; + margin: 0; } .lm_header .lm_tabdropdown_list .lm_tab .lm_title { - width: 100px; + width: 100px; } .lm_header .lm_tabdropdown_list .lm_close_tab { - display: none !important; + display: none !important; } /*********************************** * Drag Proxy ***********************************/ .lm_dragProxy { - position: absolute; - top: 0; - left: 0; - z-index: 30; + position: absolute; + top: 0; + left: 0; + z-index: 30; } .lm_dragProxy .lm_header { - background: transparent; + background: transparent; } .lm_dragProxy .lm_content { - border-top: none; - overflow: hidden; + border-top: none; + overflow: hidden; } .lm_dropTargetIndicator { - display: none; - position: absolute; - z-index: 35; - transition: all 200ms ease; + display: none; + position: absolute; + z-index: 35; + transition: all 200ms ease; } .lm_dropTargetIndicator .lm_inner { - width: 100%; - height: 100%; - position: relative; - top: 0; - left: 0; + width: 100%; + height: 100%; + position: relative; + top: 0; + left: 0; } .lm_transition_indicator { - display: none; - width: 20px; - height: 20px; - position: absolute; - top: 0; - left: 0; - z-index: 20; + display: none; + width: 20px; + height: 20px; + position: absolute; + top: 0; + left: 0; + z-index: 20; } .lm_popin { - width: 20px; - height: 20px; - position: absolute; - bottom: 0; - right: 0; - z-index: 9999; + width: 20px; + height: 20px; + position: absolute; + bottom: 0; + right: 0; + z-index: 9999; } .lm_popin > * { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; } .lm_popin > .lm_bg { - z-index: 10; + z-index: 10; } .lm_popin > .lm_icon { - z-index: 20; + z-index: 20; } :root { - /* Colors used for dark theme */ - --of-default-black: black; - --of-default-charcoal-dark: #111118; - --of-default-charcoal-light: #2A292F; - --of-default-grey-dark: #A5AEBD; - --of-default-grey-dark-opacity: #A5AEBD2E; - --of-default-grey-light: #F4F5F8; - --of-default-grey-light-opacity: #F4F5F82E; - --of-default-white: white; - --of-dark-theme: #7B7BFF; - --of-light-theme: #504CFF; - --of-highlight: #958EFF; - --of-highlight-opacity: #958EFF26; - --of-default-red: red; - --of-default-red-negative: #F55D5F; - --of-positive-green: #29AF6F; - - /* Main colors to set from the above list */ - --main-background-color: var(--of-default-charcoal-dark); - --secondary-background-color: var(--of-default-black); - --tab-background-color: var(--of-default-charcoal-light); - --tab-button-hover-color: var(--of-default-grey-dark-opacity); - --tab-button-active-color: var(--of-default-grey-light-opacity); - --tab-border-top-color: var(--of-dark-theme); - --tab-border-top-highlight-color: var(--of-light-theme); - --focused-tab-border-top-color: var(--of-positive-green); - --focused-tab-border-top-highlight-color: #3cf89d; - --tab-font-color: var(--of-default-white); - --top-bar-close-button-color: var(--of-default-red); - --top-bar-close-button-active-color: var(--of-default-red-negative); - --drop-target-border-color: var(--of-highlight); - --drop-target-background-color: var(--of-highlight-opacity); - - /* Colors that default to dependent on Main Colors, but should be uniquely editable */ - --frame-background-color: var(--secondary-background-color); - --body-font-color: var(--tab-font-color); - --splitter-color: var(--secondary-background-color); - --splitter-hover-color: var(--tab-background-color); - --tabs-bar-background-color: var(--secondary-background-color); - --title-bar-background-color: var(--main-background-color); - --color-behind-views: var(--main-background-color); /* only seen if there's a problem with the view */ - --tab-background-active-color: var(--tab-background-color); - --top-bar-button-hover-color: var(--tab-background-color); - --top-bar-button-active-color: var(--tab-button-active-color); - - /* Measurements for various components */ - --title-bar-height: 30px; - --title-bar-border-bottom-height: 1px; - --header-border-bottom-height: 2px; - --corner-radius: 0px; - --splitter-width: 4px; - - --body-container-padding-top: 0px; - --body-container-padding-right: 0px; - --body-container-padding-bottom: 0px; - --body-container-padding-left: 0px; - - --body-container-width: calc(100% - var(--body-container-padding-left) - var(--body-container-padding-right)); - --body-container-height: calc(100% - var(--title-bar-height) - var(--title-bar-border-bottom-height) - var(--body-container-padding-top) - var(--body-container-padding-bottom)); - --body-container-padding: var(--body-container-padding-top) var(--body-container-padding-right) var(--body-container-padding-bottom) var(--body-container-padding-left); - - --layout-container-padding-top: 4px; - --layout-container-padding-right: 4px; - --layout-container-padding-bottom: 4px; - --layout-container-padding-left: 4px; - --layout-container-from-top: calc(var(--title-bar-height) + var(--title-bar-border-bottom-height) + var(--layout-container-padding-top)); - - --layout-container-width: calc(100% - var(--layout-container-padding-left) - var(--layout-container-padding-right)); - --layout-container-height: calc(100% - var(--header-border-bottom-height) - var(--layout-container-padding-top) - var(--layout-container-padding-bottom)); - --layout-container-padding: var(--layout-container-padding-top) var(--layout-container-padding-right) var(--layout-container-padding-bottom) var(--layout-container-padding-left); - - /* Top Bar and Tab Icons */ - --close-button-url: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9EYXJrIFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNDI2MDEgNi4xNjEwN0M3LjA3MTcgNS45MTU2MyA2LjU4MTg0IDUuOTUwNjkgNi4yNjYyNyA2LjI2NjI3QzUuOTExMjQgNi42MjEyOSA1LjkxMTI0IDcuMTk2ODkgNi4yNjYyNyA3LjU1MTkyTDE0LjcxNDQgMTZMNi4yNjYyNyAyNC40NDgxTDYuMTYxMDcgMjQuNTc0QzUuOTE1NjMgMjQuOTI4MyA1Ljk1MDY5IDI1LjQxODIgNi4yNjYyNyAyNS43MzM3QzYuNjIxMjkgMjYuMDg4OCA3LjE5Njg5IDI2LjA4ODggNy41NTE5MiAyNS43MzM3TDE2IDE3LjI4NTZMMjQuNDQ4MSAyNS43MzM3TDI0LjU3NCAyNS44Mzg5QzI0LjkyODMgMjYuMDg0NCAyNS40MTgyIDI2LjA0OTMgMjUuNzMzNyAyNS43MzM3QzI2LjA4ODggMjUuMzc4NyAyNi4wODg4IDI0LjgwMzEgMjUuNzMzNyAyNC40NDgxTDE3LjI4NTYgMTZMMjUuNzMzNyA3LjU1MTkyTDI1LjgzODkgNy40MjYwMUMyNi4wODQ0IDcuMDcxNyAyNi4wNDkzIDYuNTgxODQgMjUuNzMzNyA2LjI2NjI3QzI1LjM3ODcgNS45MTEyNCAyNC44MDMxIDUuOTExMjQgMjQuNDQ4MSA2LjI2NjI3TDE2IDE0LjcxNDRMNy41NTE5MiA2LjI2NjI3TDcuNDI2MDEgNi4xNjEwN1oiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K"); - --minimize-button-url: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvTWluaW1pemUvV2luZG93L0RhcmsgVC4iPgo8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIzIiB5PSIyNCIgd2lkdGg9IjI2IiBoZWlnaHQ9IjMiIHJ4PSIxLjUiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K"); - --expand-button-url: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvRXhwYW5kL0RhcmsgVC4iPgo8cGF0aCBpZD0iQ29tYmluZWQgU2hhcGUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTYuOTU2NSA1TDI2LjAzNDggNS4wMDAwNEwyNi4wOTE1IDUuMDAxMThMMjYuMTQxMyA1LjAwNDk4TDI2LjIwNDMgNS4wMTM1NEwyNi4yNDE0IDUuMDIwNTFMMjYuMjc1NiA1LjAyODM1TDI2LjMwMzUgNS4wMzU3NkwyNi4zNTc3IDUuMDUyODJMMjYuNDAyOCA1LjA2OTc3TDI2LjQ1NzkgNS4wOTQxOEwyNi41MDkyIDUuMTIwNzNMMjYuNTY0MyA1LjE1NDFMMjYuNjAxMyA1LjE3OTNMMjYuNjMyNiA1LjIwMjhMMjYuNjc0IDUuMjM3MThMMjYuNzEwNSA1LjI3MDkyTDI2Ljc0MTggNS4zMDI4MkwyNi43ODEgNS4zNDczM0wyNi43OTM4IDUuMzYzMjRDMjYuODEzMyA1LjM4Nzg1IDI2LjgzMTYgNS40MTM0MyAyNi44NDg2IDUuNDM5OTFDMjYuODcgNS40NzMwNCAyNi44ODkxIDUuNTA3MjIgMjYuOTA1OSA1LjU0MjIxTDI2LjkyNDMgNS41ODI4OUwyNi45NDA2IDUuNjIzOTdMMjYuOTU2MyA1LjY3MDA1QzI2Ljk2NDkgNS42OTcyNyAyNi45NzIyIDUuNzI0OTcgMjYuOTc4MyA1Ljc1MzEyTDI2Ljk4OTYgNS44MTUxN0MyNi45OTQyIDUuODQ1OTIgMjYuOTk3MyA1Ljg3NzE1IDI2Ljk5ODggNS45MDg3OEwyNyA1Ljk1NjUyVjE1LjA0MzVDMjcgMTUuNTcxOCAyNi41NzE4IDE2IDI2LjA0MzUgMTZDMjUuNTMxMiAxNiAyNS4xMTMgMTUuNTk3MyAyNS4wODgxIDE1LjA5MTJMMjUuMDg3IDE1LjA0MzVWOC4yNjU1N0wxOC40Njk4IDE0Ljg4MjlDMTguMDk2MyAxNS4yNTY0IDE3LjQ5MDcgMTUuMjU2NCAxNy4xMTcxIDE0Ljg4MjlDMTYuNzU2IDE0LjUyMTggMTYuNzQ0IDEzLjk0MzggMTcuMDgxIDEzLjU2ODNMMTcuMTE3MSAxMy41MzAyTDIzLjczNCA2LjkxMzA0SDE2Ljk1NjVDMTYuNDI4MiA2LjkxMzA0IDE2IDYuNDg0NzkgMTYgNS45NTY1MkMxNiA1LjQ0NDI2IDE2LjQwMjcgNS4wMjYwNSAxNi45MDg4IDUuMDAxMTdMMTYuOTU2NSA1WiIgZmlsbD0iI0YyRjRGOSIvPgo8cGF0aCBpZD0iQ29tYmluZWQgU2hhcGUgQ29weSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01Ljk1NjUyIDI3TDUuOTA4NTQgMjYuOTk4OEw1Ljg1ODc0IDI2Ljk5NUw1Ljc5NTcyIDI2Ljk4NjVMNS43NTg1OCAyNi45Nzk1TDUuNzI0NDMgMjYuOTcxNkw1LjY5NjUxIDI2Ljk2NDJMNS42NDIyNyAyNi45NDcyTDUuNTk3MjMgMjYuOTMwMkw1LjU0MjEzIDI2LjkwNThMNS40OTA4NSAyNi44NzkzTDUuNDM1NjkgMjYuODQ1OUw1LjM5ODcyIDI2LjgyMDdMNS4zNjc0NCAyNi43OTcyTDUuMzI2MDQgMjYuNzYyOEw1LjI4OTUyIDI2LjcyOTFMNS4yNTgyMiAyNi42OTcyTDUuMjE5IDI2LjY1MjdMNS4yMDYxNyAyNi42MzY4QzUuMTg2NjkgMjYuNjEyMiA1LjE2ODQgMjYuNTg2NiA1LjE1MTM3IDI2LjU2MDFDNS4xMjk5NyAyNi41MjcgNS4xMTA5MSAyNi40OTI4IDUuMDk0MSAyNi40NTc4TDUuMDc1NzIgMjYuNDE3MUw1LjA1OTQyIDI2LjM3Nkw1LjA0MzcgMjYuMzI5OUM1LjAzNTEzIDI2LjMwMjcgNS4wMjc3NyAyNi4yNzUgNS4wMjE2NyAyNi4yNDY5TDUuMDEwMzcgMjYuMTg0OEM1LjAwNTgyIDI2LjE1NDEgNS4wMDI3MiAyNi4xMjI4IDUuMDAxMTcgMjYuMDkxMkw1IDI2LjA0MzVWMTYuOTU2NUM1IDE2LjQyODIgNS40MjgyNSAxNiA1Ljk1NjUyIDE2QzYuNDY4NzkgMTYgNi44ODcgMTYuNDAyNyA2LjkxMTg3IDE2LjkwODhMNi45MTMwNCAxNi45NTY1VjIzLjczNDRMMTMuNTMwMiAxNy4xMTcxQzEzLjkwMzcgMTYuNzQzNiAxNC41MDkzIDE2Ljc0MzYgMTQuODgyOSAxNy4xMTcxQzE1LjI0NCAxNy40NzgyIDE1LjI1NiAxOC4wNTYyIDE0LjkxOSAxOC40MzE3TDE0Ljg4MjkgMTguNDY5OEw4LjI2NjA0IDI1LjA4N0gxNS4wNDM1QzE1LjU3MTggMjUuMDg3IDE2IDI1LjUxNTIgMTYgMjYuMDQzNUMxNiAyNi41NTU3IDE1LjU5NzMgMjYuOTc0IDE1LjA5MTIgMjYuOTk4OEwxNS4wNDM1IDI3SDUuOTU2NTJaIiBmaWxsPSIjRjJGNEY5Ii8+CjwvZz4KPC9zdmc+Cg=="); - --tab-close-button-url: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9EYXJrIFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNDI2MDEgNi4xNjEwN0M3LjA3MTcgNS45MTU2MyA2LjU4MTg0IDUuOTUwNjkgNi4yNjYyNyA2LjI2NjI3QzUuOTExMjQgNi42MjEyOSA1LjkxMTI0IDcuMTk2ODkgNi4yNjYyNyA3LjU1MTkyTDE0LjcxNDQgMTZMNi4yNjYyNyAyNC40NDgxTDYuMTYxMDcgMjQuNTc0QzUuOTE1NjMgMjQuOTI4MyA1Ljk1MDY5IDI1LjQxODIgNi4yNjYyNyAyNS43MzM3QzYuNjIxMjkgMjYuMDg4OCA3LjE5Njg5IDI2LjA4ODggNy41NTE5MiAyNS43MzM3TDE2IDE3LjI4NTZMMjQuNDQ4MSAyNS43MzM3TDI0LjU3NCAyNS44Mzg5QzI0LjkyODMgMjYuMDg0NCAyNS40MTgyIDI2LjA0OTMgMjUuNzMzNyAyNS43MzM3QzI2LjA4ODggMjUuMzc4NyAyNi4wODg4IDI0LjgwMzEgMjUuNzMzNyAyNC40NDgxTDE3LjI4NTYgMTZMMjUuNzMzNyA3LjU1MTkyTDI1LjgzODkgNy40MjYwMUMyNi4wODQ0IDcuMDcxNyAyNi4wNDkzIDYuNTgxODQgMjUuNzMzNyA2LjI2NjI3QzI1LjM3ODcgNS45MTEyNCAyNC44MDMxIDUuOTExMjQgMjQuNDQ4MSA2LjI2NjI3TDE2IDE0LjcxNDRMNy41NTE5MiA2LjI2NjI3TDcuNDI2MDEgNi4xNjEwN1oiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K"); - --new-tab-button-url: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAJNQTFRFAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0TslXgAAADF0Uk5TAA1Zm8rs+utYJp72//WcJAmM+4oIJdTRIzHq6S8KiQ70DFaYx/lVC5kihtLPB+chLkL8Um8AAAM+SURBVHic7d3rVtNQEEDhlJZwO9xB0CAW2iAiou//dOLCpas2OTNBJtNp9n6COZ+t1T8zRUFERERERERE1FujjfFksyy3JuPtkfcsDu3s7qU/7R8ces/Tc0fHJ2mh8vTMe6Y+O3+Xlrq49J6qv95/WH5/StWV91x9dd74/meBgXwGPjZ8/n9/C4bx98Bx2/tTuvaerY92TtoByiF8CXbb35/S2Hs6+z7t5QCmN97zmbeRe39Kt97zmTfOA8y85zNvkgeYe89n3mYeoPKez7wyD1B7z2de/v0pec9nHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID3fOYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeM9nHgAAAAAAAAAAAAAAAAAAwIoDvOz/lwZe9V59v2Bh/3/0ut8vWNr/H72O9wua9v9Hr8v9gub9/9HT3y9o2/8fPe39gvb9/9FT3i/I7P+Pnup+QW7/f/RU9wuy+/+jp7hfkN//Hz3F/QJh/3/05PsFwv7/6Mn3C4T9/9GT7xcI+/+jJ98vCP//33zy/YLBA2x5j2ib/BUY/F+Cg/8Z3PYe0bY7EWC07z2jZdPPIkBx4D2kZffy+4vDNf4hrL8oAIpT7zHtetC8vzj66j2nVY/fVADFZeU9qU1P33XvL4qrtRR4+qF9//Nn4MJ72rfvUf3n/6uz6zX7LagflN//vx+C8dR76Ldreq/6/funm9vZvKq9Z//f6mo+u1P8+6+3pIG95zMPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHs+8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC85zMPAAAAAAAAAAAAAAAAAABgkADCqk55/3/0hPsF8v7/6An3C+T9/9ET7hfI+/+jJ9wvkPf/Ry9/v0Cz/z962fsFmv3/0cvdL9Dt/49e5n6Bbv9/9NrvF2j3/0ev7X6Bfv9/9JrvF3TZ/x+9pvsF3fb/R2/pfkH3/f/RW7hf8Lr9/9F7uV+wcvv/iYiIiIiIiGjt+wlaXmsfieItGAAAAABJRU5ErkJggg=="); + /* Colors used for dark theme */ + --of-default-black: black; + --of-default-charcoal-dark: #111118; + --of-default-charcoal-light: #2a292f; + --of-default-grey-dark: #a5aebd; + --of-default-grey-dark-opacity: #a5aebd2e; + --of-default-grey-light: #f4f5f8; + --of-default-grey-light-opacity: #f4f5f82e; + --of-default-white: white; + --of-dark-theme: #7b7bff; + --of-light-theme: #504cff; + --of-highlight: #958eff; + --of-highlight-opacity: #958eff26; + --of-default-red: red; + --of-default-red-negative: #f55d5f; + --of-positive-green: #29af6f; + + /* Main colors to set from the above list */ + --main-background-color: var(--of-default-charcoal-dark); + --secondary-background-color: var(--of-default-black); + --tab-background-color: var(--of-default-charcoal-light); + --tab-button-hover-color: var(--of-default-grey-dark-opacity); + --tab-button-active-color: var(--of-default-grey-light-opacity); + --tab-border-top-color: var(--of-dark-theme); + --tab-border-top-highlight-color: var(--of-light-theme); + --focused-tab-border-top-color: var(--of-positive-green); + --focused-tab-border-top-highlight-color: #3cf89d; + --tab-font-color: var(--of-default-white); + --top-bar-close-button-color: var(--of-default-red); + --top-bar-close-button-active-color: var(--of-default-red-negative); + --drop-target-border-color: var(--of-highlight); + --drop-target-background-color: var(--of-highlight-opacity); + + /* Colors that default to dependent on Main Colors, but should be uniquely editable */ + --frame-background-color: var(--secondary-background-color); + --body-font-color: var(--tab-font-color); + --splitter-color: var(--secondary-background-color); + --splitter-hover-color: var(--tab-background-color); + --tabs-bar-background-color: var(--secondary-background-color); + --title-bar-background-color: var(--main-background-color); + --color-behind-views: var(--main-background-color); /* only seen if there's a problem with the view */ + --tab-background-active-color: var(--tab-background-color); + --top-bar-button-hover-color: var(--tab-background-color); + --top-bar-button-active-color: var(--tab-button-active-color); + + /* Measurements for various components */ + --title-bar-height: 30px; + --title-bar-border-bottom-height: 1px; + --header-border-bottom-height: 2px; + --corner-radius: 0px; + --splitter-width: 4px; + + --body-container-padding-top: 0px; + --body-container-padding-right: 0px; + --body-container-padding-bottom: 0px; + --body-container-padding-left: 0px; + + --body-container-width: calc( + 100% - var(--body-container-padding-left) - var(--body-container-padding-right) + ); + --body-container-height: calc( + 100% - var(--title-bar-height) - var(--title-bar-border-bottom-height) - var(--body-container-padding-top) - + var(--body-container-padding-bottom) + ); + --body-container-padding: var(--body-container-padding-top) var(--body-container-padding-right) + var(--body-container-padding-bottom) var(--body-container-padding-left); + + --layout-container-padding-top: 4px; + --layout-container-padding-right: 4px; + --layout-container-padding-bottom: 4px; + --layout-container-padding-left: 4px; + --layout-container-from-top: calc( + var(--title-bar-height) + var(--title-bar-border-bottom-height) + var(--layout-container-padding-top) + ); + + --layout-container-width: calc( + 100% - var(--layout-container-padding-left) - var(--layout-container-padding-right) + ); + --layout-container-height: calc( + 100% - var(--header-border-bottom-height) - var(--layout-container-padding-top) - + var(--layout-container-padding-bottom) + ); + --layout-container-padding: var(--layout-container-padding-top) var(--layout-container-padding-right) + var(--layout-container-padding-bottom) var(--layout-container-padding-left); + + /* Top Bar and Tab Icons */ + --close-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9EYXJrIFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNDI2MDEgNi4xNjEwN0M3LjA3MTcgNS45MTU2MyA2LjU4MTg0IDUuOTUwNjkgNi4yNjYyNyA2LjI2NjI3QzUuOTExMjQgNi42MjEyOSA1LjkxMTI0IDcuMTk2ODkgNi4yNjYyNyA3LjU1MTkyTDE0LjcxNDQgMTZMNi4yNjYyNyAyNC40NDgxTDYuMTYxMDcgMjQuNTc0QzUuOTE1NjMgMjQuOTI4MyA1Ljk1MDY5IDI1LjQxODIgNi4yNjYyNyAyNS43MzM3QzYuNjIxMjkgMjYuMDg4OCA3LjE5Njg5IDI2LjA4ODggNy41NTE5MiAyNS43MzM3TDE2IDE3LjI4NTZMMjQuNDQ4MSAyNS43MzM3TDI0LjU3NCAyNS44Mzg5QzI0LjkyODMgMjYuMDg0NCAyNS40MTgyIDI2LjA0OTMgMjUuNzMzNyAyNS43MzM3QzI2LjA4ODggMjUuMzc4NyAyNi4wODg4IDI0LjgwMzEgMjUuNzMzNyAyNC40NDgxTDE3LjI4NTYgMTZMMjUuNzMzNyA3LjU1MTkyTDI1LjgzODkgNy40MjYwMUMyNi4wODQ0IDcuMDcxNyAyNi4wNDkzIDYuNTgxODQgMjUuNzMzNyA2LjI2NjI3QzI1LjM3ODcgNS45MTEyNCAyNC44MDMxIDUuOTExMjQgMjQuNDQ4MSA2LjI2NjI3TDE2IDE0LjcxNDRMNy41NTE5MiA2LjI2NjI3TDcuNDI2MDEgNi4xNjEwN1oiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K'); + --minimize-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvTWluaW1pemUvV2luZG93L0RhcmsgVC4iPgo8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIzIiB5PSIyNCIgd2lkdGg9IjI2IiBoZWlnaHQ9IjMiIHJ4PSIxLjUiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K'); + --expand-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvRXhwYW5kL0RhcmsgVC4iPgo8cGF0aCBpZD0iQ29tYmluZWQgU2hhcGUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTYuOTU2NSA1TDI2LjAzNDggNS4wMDAwNEwyNi4wOTE1IDUuMDAxMThMMjYuMTQxMyA1LjAwNDk4TDI2LjIwNDMgNS4wMTM1NEwyNi4yNDE0IDUuMDIwNTFMMjYuMjc1NiA1LjAyODM1TDI2LjMwMzUgNS4wMzU3NkwyNi4zNTc3IDUuMDUyODJMMjYuNDAyOCA1LjA2OTc3TDI2LjQ1NzkgNS4wOTQxOEwyNi41MDkyIDUuMTIwNzNMMjYuNTY0MyA1LjE1NDFMMjYuNjAxMyA1LjE3OTNMMjYuNjMyNiA1LjIwMjhMMjYuNjc0IDUuMjM3MThMMjYuNzEwNSA1LjI3MDkyTDI2Ljc0MTggNS4zMDI4MkwyNi43ODEgNS4zNDczM0wyNi43OTM4IDUuMzYzMjRDMjYuODEzMyA1LjM4Nzg1IDI2LjgzMTYgNS40MTM0MyAyNi44NDg2IDUuNDM5OTFDMjYuODcgNS40NzMwNCAyNi44ODkxIDUuNTA3MjIgMjYuOTA1OSA1LjU0MjIxTDI2LjkyNDMgNS41ODI4OUwyNi45NDA2IDUuNjIzOTdMMjYuOTU2MyA1LjY3MDA1QzI2Ljk2NDkgNS42OTcyNyAyNi45NzIyIDUuNzI0OTcgMjYuOTc4MyA1Ljc1MzEyTDI2Ljk4OTYgNS44MTUxN0MyNi45OTQyIDUuODQ1OTIgMjYuOTk3MyA1Ljg3NzE1IDI2Ljk5ODggNS45MDg3OEwyNyA1Ljk1NjUyVjE1LjA0MzVDMjcgMTUuNTcxOCAyNi41NzE4IDE2IDI2LjA0MzUgMTZDMjUuNTMxMiAxNiAyNS4xMTMgMTUuNTk3MyAyNS4wODgxIDE1LjA5MTJMMjUuMDg3IDE1LjA0MzVWOC4yNjU1N0wxOC40Njk4IDE0Ljg4MjlDMTguMDk2MyAxNS4yNTY0IDE3LjQ5MDcgMTUuMjU2NCAxNy4xMTcxIDE0Ljg4MjlDMTYuNzU2IDE0LjUyMTggMTYuNzQ0IDEzLjk0MzggMTcuMDgxIDEzLjU2ODNMMTcuMTE3MSAxMy41MzAyTDIzLjczNCA2LjkxMzA0SDE2Ljk1NjVDMTYuNDI4MiA2LjkxMzA0IDE2IDYuNDg0NzkgMTYgNS45NTY1MkMxNiA1LjQ0NDI2IDE2LjQwMjcgNS4wMjYwNSAxNi45MDg4IDUuMDAxMTdMMTYuOTU2NSA1WiIgZmlsbD0iI0YyRjRGOSIvPgo8cGF0aCBpZD0iQ29tYmluZWQgU2hhcGUgQ29weSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01Ljk1NjUyIDI3TDUuOTA4NTQgMjYuOTk4OEw1Ljg1ODc0IDI2Ljk5NUw1Ljc5NTcyIDI2Ljk4NjVMNS43NTg1OCAyNi45Nzk1TDUuNzI0NDMgMjYuOTcxNkw1LjY5NjUxIDI2Ljk2NDJMNS42NDIyNyAyNi45NDcyTDUuNTk3MjMgMjYuOTMwMkw1LjU0MjEzIDI2LjkwNThMNS40OTA4NSAyNi44NzkzTDUuNDM1NjkgMjYuODQ1OUw1LjM5ODcyIDI2LjgyMDdMNS4zNjc0NCAyNi43OTcyTDUuMzI2MDQgMjYuNzYyOEw1LjI4OTUyIDI2LjcyOTFMNS4yNTgyMiAyNi42OTcyTDUuMjE5IDI2LjY1MjdMNS4yMDYxNyAyNi42MzY4QzUuMTg2NjkgMjYuNjEyMiA1LjE2ODQgMjYuNTg2NiA1LjE1MTM3IDI2LjU2MDFDNS4xMjk5NyAyNi41MjcgNS4xMTA5MSAyNi40OTI4IDUuMDk0MSAyNi40NTc4TDUuMDc1NzIgMjYuNDE3MUw1LjA1OTQyIDI2LjM3Nkw1LjA0MzcgMjYuMzI5OUM1LjAzNTEzIDI2LjMwMjcgNS4wMjc3NyAyNi4yNzUgNS4wMjE2NyAyNi4yNDY5TDUuMDEwMzcgMjYuMTg0OEM1LjAwNTgyIDI2LjE1NDEgNS4wMDI3MiAyNi4xMjI4IDUuMDAxMTcgMjYuMDkxMkw1IDI2LjA0MzVWMTYuOTU2NUM1IDE2LjQyODIgNS40MjgyNSAxNiA1Ljk1NjUyIDE2QzYuNDY4NzkgMTYgNi44ODcgMTYuNDAyNyA2LjkxMTg3IDE2LjkwODhMNi45MTMwNCAxNi45NTY1VjIzLjczNDRMMTMuNTMwMiAxNy4xMTcxQzEzLjkwMzcgMTYuNzQzNiAxNC41MDkzIDE2Ljc0MzYgMTQuODgyOSAxNy4xMTcxQzE1LjI0NCAxNy40NzgyIDE1LjI1NiAxOC4wNTYyIDE0LjkxOSAxOC40MzE3TDE0Ljg4MjkgMTguNDY5OEw4LjI2NjA0IDI1LjA4N0gxNS4wNDM1QzE1LjU3MTggMjUuMDg3IDE2IDI1LjUxNTIgMTYgMjYuMDQzNUMxNiAyNi41NTU3IDE1LjU5NzMgMjYuOTc0IDE1LjA5MTIgMjYuOTk4OEwxNS4wNDM1IDI3SDUuOTU2NTJaIiBmaWxsPSIjRjJGNEY5Ii8+CjwvZz4KPC9zdmc+Cg=='); + --tab-close-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9EYXJrIFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNDI2MDEgNi4xNjEwN0M3LjA3MTcgNS45MTU2MyA2LjU4MTg0IDUuOTUwNjkgNi4yNjYyNyA2LjI2NjI3QzUuOTExMjQgNi42MjEyOSA1LjkxMTI0IDcuMTk2ODkgNi4yNjYyNyA3LjU1MTkyTDE0LjcxNDQgMTZMNi4yNjYyNyAyNC40NDgxTDYuMTYxMDcgMjQuNTc0QzUuOTE1NjMgMjQuOTI4MyA1Ljk1MDY5IDI1LjQxODIgNi4yNjYyNyAyNS43MzM3QzYuNjIxMjkgMjYuMDg4OCA3LjE5Njg5IDI2LjA4ODggNy41NTE5MiAyNS43MzM3TDE2IDE3LjI4NTZMMjQuNDQ4MSAyNS43MzM3TDI0LjU3NCAyNS44Mzg5QzI0LjkyODMgMjYuMDg0NCAyNS40MTgyIDI2LjA0OTMgMjUuNzMzNyAyNS43MzM3QzI2LjA4ODggMjUuMzc4NyAyNi4wODg4IDI0LjgwMzEgMjUuNzMzNyAyNC40NDgxTDE3LjI4NTYgMTZMMjUuNzMzNyA3LjU1MTkyTDI1LjgzODkgNy40MjYwMUMyNi4wODQ0IDcuMDcxNyAyNi4wNDkzIDYuNTgxODQgMjUuNzMzNyA2LjI2NjI3QzI1LjM3ODcgNS45MTEyNCAyNC44MDMxIDUuOTExMjQgMjQuNDQ4MSA2LjI2NjI3TDE2IDE0LjcxNDRMNy41NTE5MiA2LjI2NjI3TDcuNDI2MDEgNi4xNjEwN1oiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K'); + --new-tab-button-url: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAJNQTFRFAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0TslXgAAADF0Uk5TAA1Zm8rs+utYJp72//WcJAmM+4oIJdTRIzHq6S8KiQ70DFaYx/lVC5kihtLPB+chLkL8Um8AAAM+SURBVHic7d3rVtNQEEDhlJZwO9xB0CAW2iAiou//dOLCpas2OTNBJtNp9n6COZ+t1T8zRUFERERERERE1FujjfFksyy3JuPtkfcsDu3s7qU/7R8ces/Tc0fHJ2mh8vTMe6Y+O3+Xlrq49J6qv95/WH5/StWV91x9dd74/meBgXwGPjZ8/n9/C4bx98Bx2/tTuvaerY92TtoByiF8CXbb35/S2Hs6+z7t5QCmN97zmbeRe39Kt97zmTfOA8y85zNvkgeYe89n3mYeoPKez7wyD1B7z2de/v0pec9nHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID3fOYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeM9nHgAAAAAAAAAAAAAAAAAAwIoDvOz/lwZe9V59v2Bh/3/0ut8vWNr/H72O9wua9v9Hr8v9gub9/9HT3y9o2/8fPe39gvb9/9FT3i/I7P+Pnup+QW7/f/RU9wuy+/+jp7hfkN//Hz3F/QJh/3/05PsFwv7/6Mn3C4T9/9GT7xcI+/+jJ98vCP//33zy/YLBA2x5j2ib/BUY/F+Cg/8Z3PYe0bY7EWC07z2jZdPPIkBx4D2kZffy+4vDNf4hrL8oAIpT7zHtetC8vzj66j2nVY/fVADFZeU9qU1P33XvL4qrtRR4+qF9//Nn4MJ72rfvUf3n/6uz6zX7LagflN//vx+C8dR76Ldreq/6/funm9vZvKq9Z//f6mo+u1P8+6+3pIG95zMPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwHs+8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC85zMPAAAAAAAAAAAAAAAAAABgkADCqk55/3/0hPsF8v7/6An3C+T9/9ET7hfI+/+jJ9wvkPf/Ry9/v0Cz/z962fsFmv3/0cvdL9Dt/49e5n6Bbv9/9NrvF2j3/0ev7X6Bfv9/9JrvF3TZ/x+9pvsF3fb/R2/pfkH3/f/RW7hf8Lr9/9F7uV+wcvv/iYiIiIiIiGjt+wlaXmsfieItGAAAAABJRU5ErkJggg=='); } body { - min-height: 100%; - width: 100%; - margin: 0; - padding: 0px; - overflow: hidden; - color: var(--body-font-color); - background-color: var(--main-background-color); + min-height: 100%; + width: 100%; + margin: 0; + padding: 0px; + overflow: hidden; + color: var(--body-font-color); + background-color: var(--main-background-color); } html { - height: 100%; - width: 100%; - padding: 0px; - margin: 0; - overflow: hidden; + height: 100%; + width: 100%; + padding: 0px; + margin: 0; + overflow: hidden; } -body, select, button, li, span, div { - font-family: 'Akkurat Pro', Arial, Helvetica, sans-serif; - color: var(--body-font-color); +body, +select, +button, +li, +span, +div { + font-family: 'Akkurat Pro', Arial, Helvetica, sans-serif; + color: var(--body-font-color); } #of-frame-main { - height: 100%; - width: 100%; - padding: 0px; - margin: 0; - position: absolute; - overflow: hidden; - background-color: var(--frame-background-color); + height: 100%; + width: 100%; + padding: 0px; + margin: 0; + position: absolute; + overflow: hidden; + background-color: var(--frame-background-color); } #title-bar { - background: var(--title-bar-background-color); - width: 100%; - height: var(--title-bar-height); - display: flex; - border-bottom: var(--title-bar-border-bottom-height) solid rgba(255, 255, 255, 0.1); + background: var(--title-bar-background-color); + width: 100%; + height: var(--title-bar-height); + display: flex; + border-bottom: var(--title-bar-border-bottom-height) solid rgba(255, 255, 255, 0.1); } .title-bar-draggable { - position: relative; - flex-grow: 1; - margin: 7px 0 0 7px; /* leave grabbable margin for resize */ - -webkit-app-region: drag; - -webkit-user-select: none; + position: relative; + flex-grow: 1; + margin: 7px 0 0 7px; /* leave grabbable margin for resize */ + -webkit-app-region: drag; + -webkit-user-select: none; } div.wrapper_title { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - font-size: 3vw; - opacity: 0.5; - color: var(--tab-font-color); /* this is the text you see when a view isn't showing */ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 3vw; + opacity: 0.5; + color: var(--tab-font-color); /* this is the text you see when a view isn't showing */ } div.placeholder_image { - opacity: 0.7; - color: var(--tab-background-color); + opacity: 0.7; + color: var(--tab-background-color); } div.placeholder_image img { - height: 100%; - width: 100%; - filter: blur(6px); + height: 100%; + width: 100%; + filter: blur(6px); } #buttons-wrapper { - -webkit-app-region: none; - cursor: pointer; - user-select: none; - display: flex; - justify-content: space-between; - align-items: center; + -webkit-app-region: none; + cursor: pointer; + user-select: none; + display: flex; + justify-content: space-between; + align-items: center; } .button { - -webkit-app-region: no-drag; - vertical-align: middle; - height: 100%; - width: 30px; - background-size: 14px; - background-position: center; - background-repeat: no-repeat; + -webkit-app-region: no-drag; + vertical-align: middle; + height: 100%; + width: 30px; + background-size: 14px; + background-position: center; + background-repeat: no-repeat; } .button:hover { - background-color: var(--top-bar-button-hover-color); + background-color: var(--top-bar-button-hover-color); } .button:active { - background-color: var(--top-bar-button-active-color); + background-color: var(--top-bar-button-active-color); } #close-button:hover { - background-color: var(--top-bar-close-button-color); + background-color: var(--top-bar-close-button-color); } #close-button:active { - background-color: var(--top-bar-close-button-active-color); + background-color: var(--top-bar-close-button-active-color); } #body-container { - height: var(--body-container-height); - width: var(--body-container-width); - padding: var(--body-container-padding); + height: var(--body-container-height); + width: var(--body-container-width); + padding: var(--body-container-padding); } #layout-container { - height: var(--layout-container-height); - width: var(--layout-container-width); - padding: var(--layout-container-padding); + height: var(--layout-container-height); + width: var(--layout-container-width); + padding: var(--layout-container-padding); } .lm_header .lm_tab .lm_close_tab { - background-image: var(--tab-close-button-url); - height: 14px; - width: 14px; - background-size: 12px; - background-position: center; - border-radius: 50%; - position: absolute; /* Must be absolute, otherwise we end up with overflow errors due to inline styles */ - top: 6px; - right: 6px; + background-image: var(--tab-close-button-url); + height: 14px; + width: 14px; + background-size: 12px; + background-position: center; + border-radius: 50%; + position: absolute; /* Must be absolute, otherwise we end up with overflow errors due to inline styles */ + top: 6px; + right: 6px; } .lm_header .lm_tab .lm_close_tab:hover { - background-color: var(--tab-button-hover-color); + background-color: var(--tab-button-hover-color); } .lm_header .lm_tab .lm_close_tab:active { - background-color: var(--tab-button-active-color); + background-color: var(--tab-button-active-color); } #close-button { - background-image: var(--close-button-url); + background-image: var(--close-button-url); } #expand-button { - background-image: var(--expand-button-url); + background-image: var(--expand-button-url); } #minimize-button { - background-image: var(--minimize-button-url); + background-image: var(--minimize-button-url); } .lm_goldenlayout { - background-color: var(--frame-background-color); + background-color: var(--frame-background-color); } .lm_header { - -webkit-app-region: no-drag; - box-shadow: none; - border-bottom: var(--header-border-bottom-height) solid var(--tab-background-color); - height: 25px; - user-select: none; + -webkit-app-region: no-drag; + box-shadow: none; + border-bottom: var(--header-border-bottom-height) solid var(--tab-background-color); + height: 25px; + user-select: none; } .lm_tabs { - -webkit-app-region: no-drag; - background-color: var(--tabs-bar-background-color); - border-top-left-radius: var(--corner-radius); - border-top-right-radius: var(--corner-radius); - width: 100%; + -webkit-app-region: no-drag; + background-color: var(--tabs-bar-background-color); + border-top-left-radius: var(--corner-radius); + border-top-right-radius: var(--corner-radius); + width: 100%; } .lm_header .lm_tab { - border-top-right-radius: var(--corner-radius); - border-top-left-radius: var(--corner-radius); - background-color: var(--tab-background-color); - color: var(--tab-font-color); - height: 100%; - margin-right: 0px; - margin-top: 0px; - white-space: nowrap; - overflow-x: hidden; + border-top-right-radius: var(--corner-radius); + border-top-left-radius: var(--corner-radius); + background-color: var(--tab-background-color); + color: var(--tab-font-color); + height: 100%; + margin-right: 0px; + margin-top: 0px; + white-space: nowrap; + overflow-x: hidden; } .lm_header .lm_tabs .lm_tab { - padding-left: 8px; - padding-top: 2px; - padding-right: 8px; - padding-bottom: 2px; - border-top: 2px solid var(--tab-background-color); - opacity: 60%; - z-index: 100 !important; /* Necessary to make sure that the controls panel doesn't appear above the tabs. This is to overwrite an inline style coming from golden-layouts. */ + padding-left: 8px; + padding-top: 2px; + padding-right: 8px; + padding-bottom: 2px; + border-top: 2px solid var(--tab-background-color); + opacity: 60%; + z-index: 100 !important; /* Necessary to make sure that the controls panel doesn't appear above the tabs. This is to overwrite an inline style coming from golden-layouts. */ } .lm_header .lm_tabs .lm_tab:hover { - border-top: 2px solid var(--tab-border-top-color); /* might be able to take this out */ - opacity: 80%; + border-top: 2px solid var(--tab-border-top-color); /* might be able to take this out */ + opacity: 80%; } .lm_header .lm_tab .lm_title { - margin-right: 10px; - line-height: 25px; - font-size: 12px; - vertical-align: middle; - padding: 0; - white-space: nowrap; - color: var(--tab-font-color); - font-weight: 300; + margin-right: 10px; + line-height: 25px; + font-size: 12px; + vertical-align: middle; + padding: 0; + white-space: nowrap; + color: var(--tab-font-color); + font-weight: 300; } .lm_title { - width: 120px; - white-space: nowrap; + width: 120px; + white-space: nowrap; } .lm_header .lm_tab.lm_active { - border-top: 2px solid var(--tab-border-top-color); - background-color: var(--tab-background-active-color); - opacity: 100%; + border-top: 2px solid var(--tab-border-top-color); + background-color: var(--tab-background-active-color); + opacity: 100%; } .lm_header .lm_tabs .lm_active:hover { - border-color: var(--tab-border-top-highlight-color); - opacity: 90%; + border-color: var(--tab-border-top-highlight-color); + opacity: 90%; } .lm_content { - background-color: var(--color-behind-views); - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; + background-color: var(--color-behind-views); + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; } .lm_splitter { - background-color: var(--splitter-color); - opacity: 0.001; + background-color: var(--splitter-color); + opacity: 0.001; transition: opacity 200ms ease; } .lm_splitter:hover, .lm_splitter.lm_dragging { - background-color: var(--splitter-hover-color); - opacity: 1; + background-color: var(--splitter-hover-color); + opacity: 1; } .lm_dropTargetIndicator { - box-shadow: none; - outline: none; - transition: all 200ms ease; - background: var(--drop-target-background-color); - border: 1px solid var(--drop-target-border-color); - box-sizing: border-box; - border-radius: 2px; - margin-top: 1px; + box-shadow: none; + outline: none; + transition: all 200ms ease; + background: var(--drop-target-background-color); + border: 1px solid var(--drop-target-border-color); + box-sizing: border-box; + border-radius: 2px; + margin-top: 1px; } .lm_dropTargetIndicator .lm_inner { - background: var(--tab-background-color); - opacity: .2 + background: var(--tab-background-color); + opacity: 0.2; } .lm_tabdropdown_list { - z-index: 101 !important; + z-index: 101 !important; } - + .lm_header .lm_tabdropdown_list .lm_tab { - background-color: var(--secondary-background-color); + background-color: var(--secondary-background-color); } .lm_header .lm_tabdropdown_list .lm_tab:hover { - background-color: var(--main-background-color); + background-color: var(--main-background-color); } -.lm_header .lm_controls li.lm_tabdropdown:before{ - color: var(--tab-font-color) +.lm_header .lm_controls li.lm_tabdropdown:before { + color: var(--tab-font-color); } .lm_controls li { position: relative; background-position: center center; background-repeat: no-repeat; - opacity: .4; - transition: opacity 300ms ease + opacity: 0.4; + transition: opacity 300ms ease; } .lm_controls li:hover { - opacity: 1 + opacity: 1; } .lm_controls .lm_popout { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAPklEQVR4nI2Q0QoAIAwCNfr/X7aXCpGN8snBdgejJOzckpkxs9jR6K6T5JpU0nWl5pSXTk7qwh8SnNT+CAAWCgkKFpuSWsUAAAAASUVORK5CYII=) + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAPklEQVR4nI2Q0QoAIAwCNfr/X7aXCpGN8snBdgejJOzckpkxs9jR6K6T5JpU0nWl5pSXTk7qwh8SnNT+CAAWCgkKFpuSWsUAAAAASUVORK5CYII=); } .lm_controls .lm_maximise { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAKElEQVR4nGP8////fwYCgImQAgYGBgYWKM2IR81/okwajIpgvsMbVgAwgQYRVakEKQAAAABJRU5ErkJggg==) + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAKElEQVR4nGP8////fwYCgImQAgYGBgYWKM2IR81/okwajIpgvsMbVgAwgQYRVakEKQAAAABJRU5ErkJggg==); } .lm_controls .lm_close { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAQUlEQVR4nHXOQQ4AMAgCQeT/f6aXpsGK3jSTuCVJAAr7iBdoAwCKd0nwfaAdHbYERw5b44+E8JoBjEYGMBq5gAYP3usUDu2IvoUAAAAASUVORK5CYII=) + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAQUlEQVR4nHXOQQ4AMAgCQeT/f6aXpsGK3jSTuCVJAAr7iBdoAwCKd0nwfaAdHbYERw5b44+E8JoBjEYGMBq5gAYP3usUDu2IvoUAAAAASUVORK5CYII=); } .lm_maximised .lm_controls .lm_maximise { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJ0lEQVR4nGP8//8/AzGAiShVI1YhCwMDA8OsWbPwBmZaWhoj0SYCAN1lBxMAX4n0AAAAAElFTkSuQmCC) + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJ0lEQVR4nGP8//8/AzGAiShVI1YhCwMDA8OsWbPwBmZaWhoj0SYCAN1lBxMAX4n0AAAAAElFTkSuQmCC); } -.lm_header>.lm_tabs>.focused_tab { - border-color: var(--focused-tab-border-top-color); +.lm_header > .lm_tabs > .focused_tab { + border-color: var(--focused-tab-border-top-color); } -.lm_header>.lm_tabs>.focused_tab:hover { - border-color: var(--focused-tab-border-top-highlight-color); +.lm_header > .lm_tabs > .focused_tab:hover { + border-color: var(--focused-tab-border-top-highlight-color); } .tab-icon { - height: 12px; - width: 12px; - vertical-align: baseline; - margin-right: 7px; + height: 12px; + width: 12px; + vertical-align: baseline; + margin-right: 7px; } .lm_tabs .newTabButton { - background-image: var(--new-tab-button-url); - filter: invert(.3); + background-image: var(--new-tab-button-url); + filter: invert(0.3); background-size: cover; width: 12px; height: 12px; @@ -726,12 +745,12 @@ div.placeholder_image img { } .lm_tabs .newTabButton:hover { - filter: invert(0); + filter: invert(0); } :root.light-theme .newTabButton { - filter: invert(.7); + filter: invert(0.7); } :root.light-theme .newTabButton:hover { - filter: invert(1); -} \ No newline at end of file + filter: invert(1); +} diff --git a/how-to/web-interop-support-context-and-intents/public/views/fdc3-intent-view.html b/how-to/web-interop-support-context-and-intents/public/views/fdc3-intent-view.html new file mode 100644 index 0000000..2efafe8 --- /dev/null +++ b/how-to/web-interop-support-context-and-intents/public/views/fdc3-intent-view.html @@ -0,0 +1,45 @@ + + + + + + FDC3 View + + + + + + + +
+
+

OpenFin FDC3 Intent View

+

+ A view for presenting passed intents for ViewContact and triggering a ViewContact intent. +

+
+
+ OpenFin +
+
+
+
+ + +
+
+ + +
+
+
+ +

+			
+
+
+ +
+
+ + diff --git a/how-to/web-interop-support-context-and-intents/public/views/interop-intent-view.html b/how-to/web-interop-support-context-and-intents/public/views/interop-intent-view.html new file mode 100644 index 0000000..18e1258 --- /dev/null +++ b/how-to/web-interop-support-context-and-intents/public/views/interop-intent-view.html @@ -0,0 +1,45 @@ + + + + + + Interop View + + + + + + + +
+
+

OpenFin Interop Intent View

+

+ A view for presenting passed intents for ViewContact and triggering a ViewContact intent. +

+
+
+ OpenFin +
+
+
+
+ + +
+
+ + +
+
+
+ +

+			
+
+
+ +
+
+ + diff --git a/how-to/web-interop/public/manifest.json b/how-to/web-interop/public/manifest.json index 418bda6..d8be5c6 100644 --- a/how-to/web-interop/public/manifest.json +++ b/how-to/web-interop/public/manifest.json @@ -23,7 +23,8 @@ "method": "GET", "url": "http://localhost:6060/settings.json" } - }] + } + ] } } }