minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test minor change for pipeline test Add Gitea Actions build workflow Add CI/CD pipeline Test Build & Deploy add pipeline add pipeline2 add pipeline3 add pipeline4 add pipeline 5 add pipeline 6 add pipeline 7 add pipeline 8 add pipeline 9 add pipeline 10 add pipeline 11 add pipeline 12 add pipeline 13 add pipeline 14 add pipeline 15 add pipeline 16 add pipeline 17 add pipeline 18 add pipeline 19 add pipeline 20 add pipeline 21 add pipeline 22 add pipeline 23 add pipeline 24 1 2 3
This commit is contained in:
77
src/main/frontend/generated/jar-resources/Flow.d.ts
vendored
Normal file
77
src/main/frontend/generated/jar-resources/Flow.d.ts
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
export interface FlowConfig {
|
||||
imports?: () => Promise<any>;
|
||||
}
|
||||
interface AppConfig {
|
||||
productionMode: boolean;
|
||||
appId: string;
|
||||
uidl: any;
|
||||
}
|
||||
interface AppInitResponse {
|
||||
appConfig: AppConfig;
|
||||
pushScript?: string;
|
||||
}
|
||||
interface Router {
|
||||
render: (ctx: NavigationParameters, shouldUpdateHistory: boolean) => Promise<void>;
|
||||
}
|
||||
interface HTMLRouterContainer extends HTMLElement {
|
||||
onBeforeEnter?: (ctx: NavigationParameters, cmd: PreventAndRedirectCommands, router: Router) => void | Promise<any>;
|
||||
onBeforeLeave?: (ctx: NavigationParameters, cmd: PreventCommands, router: Router) => void | Promise<any>;
|
||||
serverConnected?: (cancel: boolean, url?: NavigationParameters) => void;
|
||||
serverPaused?: () => void;
|
||||
}
|
||||
interface FlowRoute {
|
||||
action: (params: NavigationParameters) => Promise<HTMLRouterContainer>;
|
||||
path: string;
|
||||
}
|
||||
export interface NavigationParameters {
|
||||
pathname: string;
|
||||
search?: string;
|
||||
}
|
||||
export interface PreventCommands {
|
||||
prevent: () => any;
|
||||
continue?: () => any;
|
||||
}
|
||||
export interface PreventAndRedirectCommands extends PreventCommands {
|
||||
redirect: (route: string) => any;
|
||||
}
|
||||
/**
|
||||
* Client API for flow UI operations.
|
||||
*/
|
||||
export declare class Flow {
|
||||
config: FlowConfig;
|
||||
response?: AppInitResponse;
|
||||
pathname: string;
|
||||
container: HTMLRouterContainer;
|
||||
private isActive;
|
||||
private baseRegex;
|
||||
private appShellTitle;
|
||||
private navigation;
|
||||
constructor(config?: FlowConfig);
|
||||
/**
|
||||
* Return a `route` object for vaadin-router in an one-element array.
|
||||
*
|
||||
* The `FlowRoute` object `path` property handles any route,
|
||||
* and the `action` returns the flow container without updating the content,
|
||||
* delaying the actual Flow server call to the `onBeforeEnter` phase.
|
||||
*
|
||||
* This is a specific API for its use with `vaadin-router`.
|
||||
*/
|
||||
get serverSideRoutes(): [FlowRoute];
|
||||
loadingStarted(): void;
|
||||
loadingFinished(): void;
|
||||
private get action();
|
||||
private flowLeave;
|
||||
private flowNavigate;
|
||||
private getFlowRoutePath;
|
||||
private getFlowRouteQuery;
|
||||
private flowInit;
|
||||
private loadScript;
|
||||
private findNonce;
|
||||
private injectAppIdScript;
|
||||
private flowInitClient;
|
||||
private flowInitUi;
|
||||
private addConnectionIndicator;
|
||||
private offlineStubAction;
|
||||
private isFlowClientLoaded;
|
||||
}
|
||||
export {};
|
||||
394
src/main/frontend/generated/jar-resources/Flow.js
Normal file
394
src/main/frontend/generated/jar-resources/Flow.js
Normal file
@@ -0,0 +1,394 @@
|
||||
import { ConnectionIndicator, ConnectionState } from '@vaadin/common-frontend';
|
||||
class FlowUiInitializationError extends Error {
|
||||
}
|
||||
// flow uses body for keeping references
|
||||
const flowRoot = window.document.body;
|
||||
const $wnd = window;
|
||||
const ROOT_NODE_ID = 1; // See StateTree.java
|
||||
function getClients() {
|
||||
return Object.keys($wnd.Vaadin.Flow.clients)
|
||||
.filter((key) => key !== 'TypeScript')
|
||||
.map((id) => $wnd.Vaadin.Flow.clients[id]);
|
||||
}
|
||||
function sendEvent(eventName, data) {
|
||||
getClients().forEach((client) => client.sendEventMessage(ROOT_NODE_ID, eventName, data));
|
||||
}
|
||||
/**
|
||||
* Client API for flow UI operations.
|
||||
*/
|
||||
export class Flow {
|
||||
constructor(config) {
|
||||
this.response = undefined;
|
||||
this.pathname = '';
|
||||
// flag used to inform Testbench whether a server route is in progress
|
||||
this.isActive = false;
|
||||
this.baseRegex = /^\//;
|
||||
this.navigation = '';
|
||||
flowRoot.$ = flowRoot.$ || [];
|
||||
this.config = config || {};
|
||||
// TB checks for the existence of window.Vaadin.Flow in order
|
||||
// to consider that TB needs to wait for `initFlow()`.
|
||||
$wnd.Vaadin = $wnd.Vaadin || {};
|
||||
$wnd.Vaadin.Flow = $wnd.Vaadin.Flow || {};
|
||||
$wnd.Vaadin.Flow.clients = {
|
||||
TypeScript: {
|
||||
isActive: () => this.isActive
|
||||
}
|
||||
};
|
||||
// Regular expression used to remove the app-context
|
||||
const elm = document.head.querySelector('base');
|
||||
this.baseRegex = new RegExp(`^${
|
||||
// IE11 does not support document.baseURI
|
||||
(document.baseURI || (elm && elm.href) || '/').replace(/^https?:\/\/[^/]+/i, '')}`);
|
||||
this.appShellTitle = document.title;
|
||||
// Put a vaadin-connection-indicator in the dom
|
||||
this.addConnectionIndicator();
|
||||
}
|
||||
/**
|
||||
* Return a `route` object for vaadin-router in an one-element array.
|
||||
*
|
||||
* The `FlowRoute` object `path` property handles any route,
|
||||
* and the `action` returns the flow container without updating the content,
|
||||
* delaying the actual Flow server call to the `onBeforeEnter` phase.
|
||||
*
|
||||
* This is a specific API for its use with `vaadin-router`.
|
||||
*/
|
||||
get serverSideRoutes() {
|
||||
return [
|
||||
{
|
||||
path: '(.*)',
|
||||
action: this.action
|
||||
}
|
||||
];
|
||||
}
|
||||
loadingStarted() {
|
||||
// Make Testbench know that server request is in progress
|
||||
this.isActive = true;
|
||||
$wnd.Vaadin.connectionState.loadingStarted();
|
||||
}
|
||||
loadingFinished() {
|
||||
// Make Testbench know that server request has finished
|
||||
this.isActive = false;
|
||||
$wnd.Vaadin.connectionState.loadingFinished();
|
||||
if ($wnd.Vaadin.listener) {
|
||||
// Listeners registered, do not register again.
|
||||
return;
|
||||
}
|
||||
$wnd.Vaadin.listener = {};
|
||||
// Listen for click on router-links -> 'link' navigation trigger
|
||||
// and on <a> nodes -> 'client' navigation trigger.
|
||||
// Use capture phase to detect prevented / stopped events.
|
||||
document.addEventListener('click', (_e) => {
|
||||
if (_e.target) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (_e.target.hasAttribute('router-link')) {
|
||||
this.navigation = 'link';
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
}
|
||||
else if (_e.composedPath().some((node) => node.nodeName === 'A')) {
|
||||
this.navigation = 'client';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
capture: true
|
||||
});
|
||||
}
|
||||
get action() {
|
||||
// Return a function which is bound to the flow instance, thus we can use
|
||||
// the syntax `...serverSideRoutes` in vaadin-router.
|
||||
return async (params) => {
|
||||
// Store last action pathname so as we can check it in events
|
||||
this.pathname = params.pathname;
|
||||
if ($wnd.Vaadin.connectionState.online) {
|
||||
try {
|
||||
await this.flowInit();
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof FlowUiInitializationError) {
|
||||
// error initializing Flow: assume connection lost
|
||||
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTION_LOST;
|
||||
return this.offlineStubAction();
|
||||
}
|
||||
else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// insert an offline stub
|
||||
return this.offlineStubAction();
|
||||
}
|
||||
// When an action happens, navigation will be resolved `onBeforeEnter`
|
||||
this.container.onBeforeEnter = (ctx, cmd) => this.flowNavigate(ctx, cmd);
|
||||
// For covering the 'server -> client' use case
|
||||
this.container.onBeforeLeave = (ctx, cmd) => this.flowLeave(ctx, cmd);
|
||||
return this.container;
|
||||
};
|
||||
}
|
||||
// Send a remote call to `JavaScriptBootstrapUI` to check
|
||||
// whether navigation has to be cancelled.
|
||||
async flowLeave(ctx, cmd) {
|
||||
// server -> server, viewing offline stub, or browser is offline
|
||||
const { connectionState } = $wnd.Vaadin;
|
||||
if (this.pathname === ctx.pathname || !this.isFlowClientLoaded() || connectionState.offline) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
// 'server -> client'
|
||||
return new Promise((resolve) => {
|
||||
this.loadingStarted();
|
||||
// The callback to run from server side to cancel navigation
|
||||
this.container.serverConnected = (cancel) => {
|
||||
var _a;
|
||||
resolve(cmd && cancel ? cmd.prevent() : (_a = cmd === null || cmd === void 0 ? void 0 : cmd.continue) === null || _a === void 0 ? void 0 : _a.call(cmd));
|
||||
this.loadingFinished();
|
||||
};
|
||||
// Call server side to check whether we can leave the view
|
||||
sendEvent('ui-leave-navigation', { route: this.getFlowRoutePath(ctx), query: this.getFlowRouteQuery(ctx) });
|
||||
});
|
||||
}
|
||||
// Send the remote call to `JavaScriptBootstrapUI` to render the flow
|
||||
// route specified by the context
|
||||
async flowNavigate(ctx, cmd) {
|
||||
if (this.response) {
|
||||
return new Promise((resolve) => {
|
||||
this.loadingStarted();
|
||||
// The callback to run from server side once the view is ready
|
||||
this.container.serverConnected = (cancel, redirectContext) => {
|
||||
var _a;
|
||||
if (cmd && cancel) {
|
||||
resolve(cmd.prevent());
|
||||
}
|
||||
else if (cmd && cmd.redirect && redirectContext) {
|
||||
resolve(cmd.redirect(redirectContext.pathname));
|
||||
}
|
||||
else {
|
||||
(_a = cmd === null || cmd === void 0 ? void 0 : cmd.continue) === null || _a === void 0 ? void 0 : _a.call(cmd);
|
||||
this.container.style.display = '';
|
||||
resolve(this.container);
|
||||
}
|
||||
this.loadingFinished();
|
||||
};
|
||||
this.container.serverPaused = () => {
|
||||
this.loadingFinished();
|
||||
};
|
||||
// Call server side to navigate to the given route
|
||||
sendEvent('ui-navigate', {
|
||||
route: this.getFlowRoutePath(ctx),
|
||||
query: this.getFlowRouteQuery(ctx),
|
||||
appShellTitle: this.appShellTitle,
|
||||
historyState: history.state,
|
||||
trigger: this.navigation
|
||||
});
|
||||
// Default to history navigation trigger.
|
||||
// Link and client cases are handled by click listener in loadingFinished().
|
||||
this.navigation = 'history';
|
||||
});
|
||||
}
|
||||
else {
|
||||
// No server response => offline or erroneous connection
|
||||
return Promise.resolve(this.container);
|
||||
}
|
||||
}
|
||||
getFlowRoutePath(context) {
|
||||
return decodeURIComponent(context.pathname).replace(this.baseRegex, '');
|
||||
}
|
||||
getFlowRouteQuery(context) {
|
||||
return (context.search && context.search.substring(1)) || '';
|
||||
}
|
||||
// import flow client modules and initialize UI in server side.
|
||||
async flowInit() {
|
||||
// Do not start flow twice
|
||||
if (!this.isFlowClientLoaded()) {
|
||||
$wnd.Vaadin.Flow.nonce = this.findNonce();
|
||||
// show flow progress indicator
|
||||
this.loadingStarted();
|
||||
// Initialize server side UI
|
||||
this.response = await this.flowInitUi();
|
||||
const { pushScript, appConfig } = this.response;
|
||||
if (typeof pushScript === 'string') {
|
||||
await this.loadScript(pushScript);
|
||||
}
|
||||
const { appId } = appConfig;
|
||||
// we use a custom tag for the flow app container
|
||||
// This must be created before bootstrapMod.init is called as that call
|
||||
// can handle a UIDL from the server, which relies on the container being available
|
||||
const tag = `flow-container-${appId.toLowerCase()}`;
|
||||
const serverCreatedContainer = document.querySelector(tag);
|
||||
if (serverCreatedContainer) {
|
||||
this.container = serverCreatedContainer;
|
||||
}
|
||||
else {
|
||||
this.container = document.createElement(tag);
|
||||
this.container.id = appId;
|
||||
}
|
||||
flowRoot.$[appId] = this.container;
|
||||
// Load bootstrap script with server side parameters
|
||||
const bootstrapMod = await import('./FlowBootstrap');
|
||||
bootstrapMod.init(this.response);
|
||||
// Load custom modules defined by user
|
||||
if (typeof this.config.imports === 'function') {
|
||||
this.injectAppIdScript(appId);
|
||||
await this.config.imports();
|
||||
}
|
||||
// Load flow-client module
|
||||
const clientMod = await import('./FlowClient');
|
||||
await this.flowInitClient(clientMod);
|
||||
// hide flow progress indicator
|
||||
this.loadingFinished();
|
||||
}
|
||||
// It might be that components created from server expect that their content has been rendered.
|
||||
// Appending eagerly the container we avoid these kind of errors.
|
||||
// Note that the client router will move this container to the outlet if the navigation succeed
|
||||
if (this.container && !this.container.isConnected) {
|
||||
this.container.style.display = 'none';
|
||||
document.body.appendChild(this.container);
|
||||
}
|
||||
return this.response;
|
||||
}
|
||||
async loadScript(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.onload = () => resolve();
|
||||
script.onerror = reject;
|
||||
script.src = url;
|
||||
const { nonce } = $wnd.Vaadin.Flow;
|
||||
if (nonce !== undefined) {
|
||||
script.setAttribute('nonce', nonce);
|
||||
}
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
||||
findNonce() {
|
||||
let nonce;
|
||||
const scriptTags = document.head.getElementsByTagName('script');
|
||||
for (const scriptTag of scriptTags) {
|
||||
if (scriptTag.nonce) {
|
||||
nonce = scriptTag.nonce;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nonce;
|
||||
}
|
||||
injectAppIdScript(appId) {
|
||||
const appIdWithoutHashCode = appId.substring(0, appId.lastIndexOf('-'));
|
||||
const scriptAppId = document.createElement('script');
|
||||
scriptAppId.type = 'module';
|
||||
scriptAppId.setAttribute('data-app-id', appIdWithoutHashCode);
|
||||
const { nonce } = $wnd.Vaadin.Flow;
|
||||
if (nonce !== undefined) {
|
||||
scriptAppId.setAttribute('nonce', nonce);
|
||||
}
|
||||
document.body.append(scriptAppId);
|
||||
}
|
||||
// After the flow-client javascript module has been loaded, this initializes flow UI
|
||||
// in the browser.
|
||||
async flowInitClient(clientMod) {
|
||||
clientMod.init();
|
||||
// client init is async, we need to loop until initialized
|
||||
return new Promise((resolve) => {
|
||||
const intervalId = setInterval(() => {
|
||||
// client `isActive() == true` while initializing or processing
|
||||
const initializing = getClients().reduce((prev, client) => prev || client.isActive(), false);
|
||||
if (!initializing) {
|
||||
clearInterval(intervalId);
|
||||
resolve();
|
||||
}
|
||||
}, 5);
|
||||
});
|
||||
}
|
||||
// Returns the `appConfig` object
|
||||
async flowInitUi() {
|
||||
// appConfig was sent in the index.html request
|
||||
const initial = $wnd.Vaadin && $wnd.Vaadin.TypeScript && $wnd.Vaadin.TypeScript.initial;
|
||||
if (initial) {
|
||||
$wnd.Vaadin.TypeScript.initial = undefined;
|
||||
return Promise.resolve(initial);
|
||||
}
|
||||
// send a request to the `JavaScriptBootstrapHandler`
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
const httpRequest = xhr;
|
||||
const requestPath = `?v-r=init&location=${encodeURIComponent(this.getFlowRoutePath(location))}&query=${encodeURIComponent(this.getFlowRouteQuery(location))}`;
|
||||
httpRequest.open('GET', requestPath);
|
||||
httpRequest.onerror = () => reject(new FlowUiInitializationError(`Invalid server response when initializing Flow UI.
|
||||
${httpRequest.status}
|
||||
${httpRequest.responseText}`));
|
||||
httpRequest.onload = () => {
|
||||
const contentType = httpRequest.getResponseHeader('content-type');
|
||||
if (contentType && contentType.indexOf('application/json') !== -1) {
|
||||
resolve(JSON.parse(httpRequest.responseText));
|
||||
}
|
||||
else {
|
||||
httpRequest.onerror();
|
||||
}
|
||||
};
|
||||
httpRequest.send();
|
||||
});
|
||||
}
|
||||
// Create shared connection state store and connection indicator
|
||||
addConnectionIndicator() {
|
||||
// add connection indicator to DOM
|
||||
ConnectionIndicator.create();
|
||||
// Listen to browser online/offline events and update the loading indicator accordingly.
|
||||
// Note: if flow-client is loaded, it instead handles the state transitions.
|
||||
$wnd.addEventListener('online', () => {
|
||||
if (!this.isFlowClientLoaded()) {
|
||||
// Send an HTTP HEAD request for sw.js to verify server reachability.
|
||||
// We do not expect sw.js to be cached, so the request goes to the
|
||||
// server rather than being served from local cache.
|
||||
// Require network-level failure to revert the state to CONNECTION_LOST
|
||||
// (HTTP error code is ok since it still verifies server's presence).
|
||||
$wnd.Vaadin.connectionState.state = ConnectionState.RECONNECTING;
|
||||
const http = new XMLHttpRequest();
|
||||
http.open('HEAD', 'sw.js');
|
||||
http.onload = () => {
|
||||
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTED;
|
||||
};
|
||||
http.onerror = () => {
|
||||
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTION_LOST;
|
||||
};
|
||||
// Postpone request to reduce potential net::ERR_INTERNET_DISCONNECTED
|
||||
// errors that sometimes occurs even if browser says it is online
|
||||
setTimeout(() => http.send(), 50);
|
||||
}
|
||||
});
|
||||
$wnd.addEventListener('offline', () => {
|
||||
if (!this.isFlowClientLoaded()) {
|
||||
$wnd.Vaadin.connectionState.state = ConnectionState.CONNECTION_LOST;
|
||||
}
|
||||
});
|
||||
}
|
||||
async offlineStubAction() {
|
||||
const offlineStub = document.createElement('iframe');
|
||||
const offlineStubPath = './offline-stub.html';
|
||||
offlineStub.setAttribute('src', offlineStubPath);
|
||||
offlineStub.setAttribute('style', 'width: 100%; height: 100%; border: 0');
|
||||
this.response = undefined;
|
||||
let onlineListener;
|
||||
const removeOfflineStubAndOnlineListener = () => {
|
||||
if (onlineListener !== undefined) {
|
||||
$wnd.Vaadin.connectionState.removeStateChangeListener(onlineListener);
|
||||
onlineListener = undefined;
|
||||
}
|
||||
};
|
||||
offlineStub.onBeforeEnter = (ctx, _cmds, router) => {
|
||||
onlineListener = () => {
|
||||
if ($wnd.Vaadin.connectionState.online) {
|
||||
removeOfflineStubAndOnlineListener();
|
||||
router.render(ctx, false);
|
||||
}
|
||||
};
|
||||
$wnd.Vaadin.connectionState.addStateChangeListener(onlineListener);
|
||||
};
|
||||
offlineStub.onBeforeLeave = (_ctx, _cmds, _router) => {
|
||||
removeOfflineStubAndOnlineListener();
|
||||
};
|
||||
return offlineStub;
|
||||
}
|
||||
isFlowClientLoaded() {
|
||||
return this.response !== undefined;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=Flow.js.map
|
||||
1
src/main/frontend/generated/jar-resources/Flow.js.map
Normal file
1
src/main/frontend/generated/jar-resources/Flow.js.map
Normal file
File diff suppressed because one or more lines are too long
1
src/main/frontend/generated/jar-resources/FlowBootstrap.d.ts
vendored
Normal file
1
src/main/frontend/generated/jar-resources/FlowBootstrap.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export const init: (appInitResponse: any) => void;
|
||||
291
src/main/frontend/generated/jar-resources/FlowBootstrap.js
Normal file
291
src/main/frontend/generated/jar-resources/FlowBootstrap.js
Normal file
@@ -0,0 +1,291 @@
|
||||
/* This is a copy of the regular `BootstrapHandler.js` in the flow-server
|
||||
module, but with the following modifications:
|
||||
- The main function is exported as an ES module for lazy initialization.
|
||||
- Application configuration is passed as a parameter instead of using
|
||||
replacement placeholders as in the regular bootstrapping.
|
||||
- It reuses `Vaadin.Flow.clients` if exists.
|
||||
- Fixed lint errors.
|
||||
*/
|
||||
const init = function (appInitResponse) {
|
||||
window.Vaadin = window.Vaadin || {};
|
||||
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||
|
||||
var apps = {};
|
||||
var widgetsets = {};
|
||||
|
||||
var log;
|
||||
if (typeof window.console === undefined || !window.location.search.match(/[&?]debug(&|$)/)) {
|
||||
/* If no console.log present, just use a no-op */
|
||||
log = function () {};
|
||||
} else if (typeof window.console.log === 'function') {
|
||||
/* If it's a function, use it with apply */
|
||||
log = function () {
|
||||
window.console.log.apply(window.console, arguments);
|
||||
};
|
||||
} else {
|
||||
/* In IE, its a native function for which apply is not defined, but it works
|
||||
without a proper 'this' reference */
|
||||
log = window.console.log;
|
||||
}
|
||||
|
||||
var isInitializedInDom = function (appId) {
|
||||
var appDiv = document.getElementById(appId);
|
||||
if (!appDiv) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < appDiv.childElementCount; i++) {
|
||||
var className = appDiv.childNodes[i].className;
|
||||
/* If the app div contains a child with the class
|
||||
'v-app-loading' we have only received the HTML
|
||||
but not yet started the widget set
|
||||
(UIConnector removes the v-app-loading div). */
|
||||
if (className && className.indexOf('v-app-loading') != -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/*
|
||||
* Needed for Testbench compatibility, but prevents any Vaadin 7 app from
|
||||
* bootstrapping unless the legacy vaadinBootstrap.js file is loaded before
|
||||
* this script.
|
||||
*/
|
||||
window.Vaadin = window.Vaadin || {};
|
||||
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||
|
||||
/*
|
||||
* Needed for wrapping custom javascript functionality in the components (i.e. connectors)
|
||||
*/
|
||||
window.Vaadin.Flow.tryCatchWrapper = function (originalFunction, component) {
|
||||
return function () {
|
||||
try {
|
||||
// eslint-disable-next-line
|
||||
const result = originalFunction.apply(this, arguments);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`There seems to be an error in ${component}:
|
||||
${error.message}
|
||||
Please submit an issue to https://github.com/vaadin/flow-components/issues/new/choose`
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if (!window.Vaadin.Flow.initApplication) {
|
||||
window.Vaadin.Flow.clients = window.Vaadin.Flow.clients || {};
|
||||
|
||||
window.Vaadin.Flow.initApplication = function (appId, config) {
|
||||
var testbenchId = appId.replace(/-\d+$/, '');
|
||||
|
||||
if (apps[appId]) {
|
||||
if (
|
||||
window.Vaadin &&
|
||||
window.Vaadin.Flow &&
|
||||
window.Vaadin.Flow.clients &&
|
||||
window.Vaadin.Flow.clients[testbenchId] &&
|
||||
window.Vaadin.Flow.clients[testbenchId].initializing
|
||||
) {
|
||||
throw new Error('Application ' + appId + ' is already being initialized');
|
||||
}
|
||||
if (isInitializedInDom(appId)) {
|
||||
if (appInitResponse.appConfig.productionMode) {
|
||||
throw new Error('Application ' + appId + ' already initialized');
|
||||
}
|
||||
|
||||
// Remove old contents for Flow
|
||||
var appDiv = document.getElementById(appId);
|
||||
for (var i = 0; i < appDiv.childElementCount; i++) {
|
||||
appDiv.childNodes[i].remove();
|
||||
}
|
||||
|
||||
// For devMode reset app config and restart widgetset as client
|
||||
// is up and running after hrm update.
|
||||
const getConfig = function (name) {
|
||||
return config[name];
|
||||
};
|
||||
|
||||
/* Export public data */
|
||||
const app = {
|
||||
getConfig: getConfig
|
||||
};
|
||||
apps[appId] = app;
|
||||
|
||||
if (widgetsets['client'].callback) {
|
||||
log('Starting from bootstrap', appId);
|
||||
widgetsets['client'].callback(appId);
|
||||
} else {
|
||||
log('Setting pending startup', appId);
|
||||
widgetsets['client'].pendingApps.push(appId);
|
||||
}
|
||||
return apps[appId];
|
||||
}
|
||||
}
|
||||
|
||||
log('init application', appId, config);
|
||||
|
||||
window.Vaadin.Flow.clients[testbenchId] = {
|
||||
isActive: function () {
|
||||
return true;
|
||||
},
|
||||
initializing: true,
|
||||
productionMode: mode
|
||||
};
|
||||
|
||||
var getConfig = function (name) {
|
||||
var value = config[name];
|
||||
return value;
|
||||
};
|
||||
|
||||
/* Export public data */
|
||||
var app = {
|
||||
getConfig: getConfig
|
||||
};
|
||||
apps[appId] = app;
|
||||
|
||||
if (!window.name) {
|
||||
window.name = appId + '-' + Math.random();
|
||||
}
|
||||
|
||||
var widgetset = 'client';
|
||||
widgetsets[widgetset] = {
|
||||
pendingApps: []
|
||||
};
|
||||
if (widgetsets[widgetset].callback) {
|
||||
log('Starting from bootstrap', appId);
|
||||
widgetsets[widgetset].callback(appId);
|
||||
} else {
|
||||
log('Setting pending startup', appId);
|
||||
widgetsets[widgetset].pendingApps.push(appId);
|
||||
}
|
||||
|
||||
return app;
|
||||
};
|
||||
window.Vaadin.Flow.getAppIds = function () {
|
||||
var ids = [];
|
||||
for (var id in apps) {
|
||||
if (Object.prototype.hasOwnProperty.call(apps, id)) {
|
||||
ids.push(id);
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
};
|
||||
window.Vaadin.Flow.getApp = function (appId) {
|
||||
return apps[appId];
|
||||
};
|
||||
window.Vaadin.Flow.registerWidgetset = function (widgetset, callback) {
|
||||
log('Widgetset registered', widgetset);
|
||||
var ws = widgetsets[widgetset];
|
||||
if (ws && ws.pendingApps) {
|
||||
ws.callback = callback;
|
||||
for (var i = 0; i < ws.pendingApps.length; i++) {
|
||||
var appId = ws.pendingApps[i];
|
||||
log('Starting from register widgetset', appId);
|
||||
callback(appId);
|
||||
}
|
||||
ws.pendingApps = null;
|
||||
}
|
||||
};
|
||||
window.Vaadin.Flow.getBrowserDetailsParameters = function () {
|
||||
var params = {};
|
||||
|
||||
/* Screen height and width */
|
||||
params['v-sh'] = window.screen.height;
|
||||
params['v-sw'] = window.screen.width;
|
||||
/* Browser window dimensions */
|
||||
params['v-wh'] = window.innerHeight;
|
||||
params['v-ww'] = window.innerWidth;
|
||||
/* Body element dimensions */
|
||||
params['v-bh'] = document.body.clientHeight;
|
||||
params['v-bw'] = document.body.clientWidth;
|
||||
|
||||
/* Current time */
|
||||
var date = new Date();
|
||||
params['v-curdate'] = date.getTime();
|
||||
|
||||
/* Current timezone offset (including DST shift) */
|
||||
var tzo1 = date.getTimezoneOffset();
|
||||
|
||||
/* Compare the current tz offset with the first offset from the end
|
||||
of the year that differs --- if less that, we are in DST, otherwise
|
||||
we are in normal time */
|
||||
var dstDiff = 0;
|
||||
var rawTzo = tzo1;
|
||||
for (var m = 12; m > 0; m--) {
|
||||
date.setUTCMonth(m);
|
||||
var tzo2 = date.getTimezoneOffset();
|
||||
if (tzo1 != tzo2) {
|
||||
dstDiff = tzo1 > tzo2 ? tzo1 - tzo2 : tzo2 - tzo1;
|
||||
rawTzo = tzo1 > tzo2 ? tzo1 : tzo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time zone offset */
|
||||
params['v-tzo'] = tzo1;
|
||||
|
||||
/* DST difference */
|
||||
params['v-dstd'] = dstDiff;
|
||||
|
||||
/* Time zone offset without DST */
|
||||
params['v-rtzo'] = rawTzo;
|
||||
|
||||
/* DST in effect? */
|
||||
params['v-dston'] = tzo1 != rawTzo;
|
||||
|
||||
/* Time zone id (if available) */
|
||||
try {
|
||||
params['v-tzid'] = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
} catch (err) {
|
||||
params['v-tzid'] = '';
|
||||
}
|
||||
|
||||
/* Window name */
|
||||
if (window.name) {
|
||||
params['v-wn'] = window.name;
|
||||
}
|
||||
|
||||
/* Detect touch device support */
|
||||
var supportsTouch = false;
|
||||
try {
|
||||
document.createEvent('TouchEvent');
|
||||
supportsTouch = true;
|
||||
} catch (e) {
|
||||
/* Chrome and IE10 touch detection */
|
||||
supportsTouch = 'ontouchstart' in window || typeof navigator.msMaxTouchPoints !== 'undefined';
|
||||
}
|
||||
params['v-td'] = supportsTouch;
|
||||
|
||||
/* Device Pixel Ratio */
|
||||
params['v-pr'] = window.devicePixelRatio;
|
||||
|
||||
if (navigator.platform) {
|
||||
params['v-np'] = navigator.platform;
|
||||
}
|
||||
|
||||
/* Stringify each value (they are parsed on the server side) */
|
||||
Object.keys(params).forEach(function (key) {
|
||||
var value = params[key];
|
||||
if (typeof value !== 'undefined') {
|
||||
params[key] = value.toString();
|
||||
}
|
||||
});
|
||||
return params;
|
||||
};
|
||||
}
|
||||
|
||||
log('Flow bootstrap loaded');
|
||||
if (appInitResponse.appConfig.productionMode && typeof window.__gwtStatsEvent != 'function') {
|
||||
window.Vaadin.Flow.gwtStatsEvents = [];
|
||||
window.__gwtStatsEvent = function (event) {
|
||||
window.Vaadin.Flow.gwtStatsEvents.push(event);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
var config = appInitResponse.appConfig;
|
||||
var mode = appInitResponse.appConfig.productionMode;
|
||||
window.Vaadin.Flow.initApplication(config.appId, config);
|
||||
};
|
||||
|
||||
export { init };
|
||||
1
src/main/frontend/generated/jar-resources/FlowClient.d.ts
vendored
Normal file
1
src/main/frontend/generated/jar-resources/FlowClient.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export const init: () => void;
|
||||
1082
src/main/frontend/generated/jar-resources/FlowClient.js
Normal file
1082
src/main/frontend/generated/jar-resources/FlowClient.js
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
|
||||
import { Outlet } from 'react-router';
|
||||
import { ReactAdapterElement } from "Frontend/generated/flow/ReactAdapter.js";
|
||||
import React from "react";
|
||||
|
||||
class ReactRouterOutletElement extends ReactAdapterElement {
|
||||
public async connectedCallback() {
|
||||
await super.connectedCallback();
|
||||
this.style.display = 'contents';
|
||||
}
|
||||
|
||||
protected render(): React.ReactElement | null {
|
||||
return <Outlet />;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define('react-router-outlet', ReactRouterOutletElement);
|
||||
277
src/main/frontend/generated/jar-resources/comboBoxConnector.js
Normal file
277
src/main/frontend/generated/jar-resources/comboBoxConnector.js
Normal file
@@ -0,0 +1,277 @@
|
||||
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
||||
import { timeOut } from '@vaadin/component-base/src/async.js';
|
||||
import { ComboBoxPlaceholder } from '@vaadin/combo-box/src/vaadin-combo-box-placeholder.js';
|
||||
|
||||
window.Vaadin.Flow.comboBoxConnector = {};
|
||||
window.Vaadin.Flow.comboBoxConnector.initLazy = (comboBox) => {
|
||||
// Check whether the connector was already initialized for the ComboBox
|
||||
if (comboBox.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
comboBox.$connector = {};
|
||||
|
||||
// holds pageIndex -> callback pairs of subsequent indexes (current active range)
|
||||
const pageCallbacks = {};
|
||||
let cache = {};
|
||||
let lastFilter = '';
|
||||
const placeHolder = new window.Vaadin.ComboBoxPlaceholder();
|
||||
|
||||
const serverFacade = (() => {
|
||||
// Private variables
|
||||
let lastFilterSentToServer = '';
|
||||
let dataCommunicatorResetNeeded = false;
|
||||
|
||||
// Public methods
|
||||
const needsDataCommunicatorReset = () => (dataCommunicatorResetNeeded = true);
|
||||
const getLastFilterSentToServer = () => lastFilterSentToServer;
|
||||
const requestData = (startIndex, endIndex, params) => {
|
||||
const count = endIndex - startIndex;
|
||||
const filter = params.filter;
|
||||
|
||||
comboBox.$server.setRequestedRange(startIndex, count, filter);
|
||||
lastFilterSentToServer = filter;
|
||||
if (dataCommunicatorResetNeeded) {
|
||||
comboBox.$server.resetDataCommunicator();
|
||||
dataCommunicatorResetNeeded = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
needsDataCommunicatorReset,
|
||||
getLastFilterSentToServer,
|
||||
requestData
|
||||
};
|
||||
})();
|
||||
|
||||
const clearPageCallbacks = (pages = Object.keys(pageCallbacks)) => {
|
||||
// Flush and empty the existing requests
|
||||
pages.forEach((page) => {
|
||||
pageCallbacks[page]([], comboBox.size);
|
||||
delete pageCallbacks[page];
|
||||
|
||||
// Empty the comboBox's internal cache without invoking observers by filling
|
||||
// the filteredItems array with placeholders (comboBox will request for data when it
|
||||
// encounters a placeholder)
|
||||
const pageStart = parseInt(page) * comboBox.pageSize;
|
||||
const pageEnd = pageStart + comboBox.pageSize;
|
||||
const end = Math.min(pageEnd, comboBox.filteredItems.length);
|
||||
for (let i = pageStart; i < end; i++) {
|
||||
comboBox.filteredItems[i] = placeHolder;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
comboBox.dataProvider = function (params, callback) {
|
||||
if (params.pageSize != comboBox.pageSize) {
|
||||
throw 'Invalid pageSize';
|
||||
}
|
||||
|
||||
if (comboBox._clientSideFilter) {
|
||||
// For clientside filter we first make sure we have all data which we also
|
||||
// filter based on comboBox.filter. While later we only filter clientside data.
|
||||
|
||||
if (cache[0]) {
|
||||
performClientSideFilter(cache[0], params.filter, callback);
|
||||
return;
|
||||
} else {
|
||||
// If client side filter is enabled then we need to first ask all data
|
||||
// and filter it on client side, otherwise next time when user will
|
||||
// input another filter, eg. continue to type, the local cache will be only
|
||||
// what was received for the first filter, which may not be the whole
|
||||
// data from server (keep in mind that client side filter is enabled only
|
||||
// when the items count does not exceed one page).
|
||||
params.filter = '';
|
||||
}
|
||||
}
|
||||
|
||||
const filterChanged = params.filter !== lastFilter;
|
||||
if (filterChanged) {
|
||||
cache = {};
|
||||
lastFilter = params.filter;
|
||||
this._filterDebouncer = Debouncer.debounce(this._filterDebouncer, timeOut.after(500), () => {
|
||||
if (serverFacade.getLastFilterSentToServer() === params.filter) {
|
||||
// Fixes the case when the filter changes
|
||||
// to something else and back to the original value
|
||||
// within debounce timeout, and the
|
||||
// DataCommunicator thinks it doesn't need to send data
|
||||
serverFacade.needsDataCommunicatorReset();
|
||||
}
|
||||
if (params.filter !== lastFilter) {
|
||||
throw new Error("Expected params.filter to be '" + lastFilter + "' but was '" + params.filter + "'");
|
||||
}
|
||||
// Remove the debouncer before clearing page callbacks.
|
||||
// This makes sure that they are executed.
|
||||
this._filterDebouncer = undefined;
|
||||
// Call the method again after debounce.
|
||||
clearPageCallbacks();
|
||||
comboBox.dataProvider(params, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Postpone the execution of new callbacks if there is an active debouncer.
|
||||
// They will be executed when the page callbacks are cleared within the debouncer.
|
||||
if (this._filterDebouncer) {
|
||||
pageCallbacks[params.page] = callback;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cache[params.page]) {
|
||||
// This may happen after skipping pages by scrolling fast
|
||||
commitPage(params.page, callback);
|
||||
} else {
|
||||
pageCallbacks[params.page] = callback;
|
||||
const maxRangeCount = Math.max(params.pageSize * 2, 500); // Max item count in active range
|
||||
const activePages = Object.keys(pageCallbacks).map((page) => parseInt(page));
|
||||
const rangeMin = Math.min(...activePages);
|
||||
const rangeMax = Math.max(...activePages);
|
||||
|
||||
if (activePages.length * params.pageSize > maxRangeCount) {
|
||||
if (params.page === rangeMin) {
|
||||
clearPageCallbacks([String(rangeMax)]);
|
||||
} else {
|
||||
clearPageCallbacks([String(rangeMin)]);
|
||||
}
|
||||
comboBox.dataProvider(params, callback);
|
||||
} else if (rangeMax - rangeMin + 1 !== activePages.length) {
|
||||
// Wasn't a sequential page index, clear the cache so combo-box will request for new pages
|
||||
clearPageCallbacks();
|
||||
} else {
|
||||
// The requested page was sequential, extend the requested range
|
||||
const startIndex = params.pageSize * rangeMin;
|
||||
const endIndex = params.pageSize * (rangeMax + 1);
|
||||
|
||||
serverFacade.requestData(startIndex, endIndex, params);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
comboBox.$connector.clear = (start, length) => {
|
||||
const firstPageToClear = Math.floor(start / comboBox.pageSize);
|
||||
const numberOfPagesToClear = Math.ceil(length / comboBox.pageSize);
|
||||
|
||||
for (let i = firstPageToClear; i < firstPageToClear + numberOfPagesToClear; i++) {
|
||||
delete cache[i];
|
||||
}
|
||||
};
|
||||
|
||||
comboBox.$connector.filter = (item, filter) => {
|
||||
filter = filter ? filter.toString().toLowerCase() : '';
|
||||
return comboBox._getItemLabel(item, comboBox.itemLabelPath).toString().toLowerCase().indexOf(filter) > -1;
|
||||
};
|
||||
|
||||
comboBox.$connector.set = (index, items, filter) => {
|
||||
if (filter != serverFacade.getLastFilterSentToServer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index % comboBox.pageSize != 0) {
|
||||
throw 'Got new data to index ' + index + ' which is not aligned with the page size of ' + comboBox.pageSize;
|
||||
}
|
||||
|
||||
if (index === 0 && items.length === 0 && pageCallbacks[0]) {
|
||||
// Makes sure that the dataProvider callback is called even when server
|
||||
// returns empty data set (no items match the filter).
|
||||
cache[0] = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const firstPageToSet = index / comboBox.pageSize;
|
||||
const updatedPageCount = Math.ceil(items.length / comboBox.pageSize);
|
||||
|
||||
for (let i = 0; i < updatedPageCount; i++) {
|
||||
let page = firstPageToSet + i;
|
||||
let slice = items.slice(i * comboBox.pageSize, (i + 1) * comboBox.pageSize);
|
||||
|
||||
cache[page] = slice;
|
||||
}
|
||||
};
|
||||
|
||||
comboBox.$connector.updateData = (items) => {
|
||||
const itemsMap = new Map(items.map((item) => [item.key, item]));
|
||||
|
||||
comboBox.filteredItems = comboBox.filteredItems.map((item) => {
|
||||
return itemsMap.get(item.key) || item;
|
||||
});
|
||||
};
|
||||
|
||||
comboBox.$connector.updateSize = function (newSize) {
|
||||
if (!comboBox._clientSideFilter) {
|
||||
// FIXME: It may be that this size set is unnecessary, since when
|
||||
// providing data to combobox via callback we may use data's size.
|
||||
// However, if this size reflect the whole data size, including
|
||||
// data not fetched yet into client side, and combobox expect it
|
||||
// to be set as such, the at least, we don't need it in case the
|
||||
// filter is clientSide only, since it'll increase the height of
|
||||
// the popup at only at first user filter to this size, while the
|
||||
// filtered items count are less.
|
||||
comboBox.size = newSize;
|
||||
}
|
||||
};
|
||||
|
||||
comboBox.$connector.reset = function () {
|
||||
clearPageCallbacks();
|
||||
cache = {};
|
||||
comboBox.clearCache();
|
||||
};
|
||||
|
||||
comboBox.$connector.confirm = function (id, filter) {
|
||||
if (filter != serverFacade.getLastFilterSentToServer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We're done applying changes from this batch, resolve pending
|
||||
// callbacks
|
||||
let activePages = Object.getOwnPropertyNames(pageCallbacks);
|
||||
for (let i = 0; i < activePages.length; i++) {
|
||||
let page = activePages[i];
|
||||
|
||||
if (cache[page]) {
|
||||
commitPage(page, pageCallbacks[page]);
|
||||
}
|
||||
}
|
||||
|
||||
// Let server know we're done
|
||||
comboBox.$server.confirmUpdate(id);
|
||||
};
|
||||
|
||||
const commitPage = function (page, callback) {
|
||||
let data = cache[page];
|
||||
|
||||
if (comboBox._clientSideFilter) {
|
||||
performClientSideFilter(data, comboBox.filter, callback);
|
||||
} else {
|
||||
// Remove the data if server-side filtering, but keep it for client-side
|
||||
// filtering
|
||||
delete cache[page];
|
||||
|
||||
// FIXME: It may be that we ought to provide data.length instead of
|
||||
// comboBox.size and remove updateSize function.
|
||||
callback(data, comboBox.size);
|
||||
}
|
||||
};
|
||||
|
||||
// Perform filter on client side (here) using the items from specified page
|
||||
// and submitting the filtered items to specified callback.
|
||||
// The filter used is the one from combobox, not the lastFilter stored since
|
||||
// that may not reflect user's input.
|
||||
const performClientSideFilter = function (page, filter, callback) {
|
||||
let filteredItems = page;
|
||||
|
||||
if (filter) {
|
||||
filteredItems = page.filter((item) => comboBox.$connector.filter(item, filter));
|
||||
}
|
||||
|
||||
callback(filteredItems, filteredItems.length);
|
||||
};
|
||||
|
||||
// Prevent setting the custom value as the 'value'-prop automatically
|
||||
comboBox.addEventListener('custom-value-set', (e) => e.preventDefault());
|
||||
|
||||
comboBox.itemClassNameGenerator = function (item) {
|
||||
return item.className || '';
|
||||
};
|
||||
};
|
||||
|
||||
window.Vaadin.ComboBoxPlaceholder = ComboBoxPlaceholder;
|
||||
@@ -0,0 +1,122 @@
|
||||
function getContainer(appId, nodeId) {
|
||||
try {
|
||||
return window.Vaadin.Flow.clients[appId].getByNodeId(nodeId);
|
||||
} catch (error) {
|
||||
console.error('Could not get node %s from app %s', nodeId, appId);
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the connector for a context menu element.
|
||||
*
|
||||
* @param {HTMLElement} contextMenu
|
||||
* @param {string} appId
|
||||
*/
|
||||
function initLazy(contextMenu, appId) {
|
||||
if (contextMenu.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
contextMenu.$connector = {
|
||||
/**
|
||||
* Generates and assigns the items to the context menu.
|
||||
*
|
||||
* @param {number} nodeId
|
||||
*/
|
||||
generateItems(nodeId) {
|
||||
const items = generateItemsTree(appId, nodeId);
|
||||
|
||||
contextMenu.items = items;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an items tree compatible with the context-menu web component
|
||||
* by traversing the given Flow DOM tree of context menu item nodes
|
||||
* whose root node is identified by the `nodeId` argument.
|
||||
*
|
||||
* The app id is required to access the store of Flow DOM nodes.
|
||||
*
|
||||
* @param {string} appId
|
||||
* @param {number} nodeId
|
||||
*/
|
||||
function generateItemsTree(appId, nodeId) {
|
||||
const container = getContainer(appId, nodeId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Array.from(container.children).map((child) => {
|
||||
const item = {
|
||||
component: child,
|
||||
checked: child._checked,
|
||||
keepOpen: child._keepOpen,
|
||||
className: child.className,
|
||||
theme: child.__theme
|
||||
};
|
||||
// Do not hardcode tag name to allow `vaadin-menu-bar-item`
|
||||
if (child._hasVaadinItemMixin && child._containerNodeId) {
|
||||
item.children = generateItemsTree(appId, child._containerNodeId);
|
||||
}
|
||||
child._item = item;
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the checked state for a context menu item.
|
||||
*
|
||||
* This method is supposed to be called when the context menu item is closed,
|
||||
* so there is no need for triggering a re-render eagarly.
|
||||
*
|
||||
* @param {HTMLElement} component
|
||||
* @param {boolean} checked
|
||||
*/
|
||||
function setChecked(component, checked) {
|
||||
if (component._item) {
|
||||
component._item.checked = checked;
|
||||
|
||||
// Set the attribute in the connector to show the checkmark
|
||||
// without having to re-render the whole menu while opened.
|
||||
if (component._item.keepOpen) {
|
||||
component.toggleAttribute('menu-item-checked', checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keep open state for a context menu item.
|
||||
*
|
||||
* @param {HTMLElement} component
|
||||
* @param {boolean} keepOpen
|
||||
*/
|
||||
function setKeepOpen(component, keepOpen) {
|
||||
if (component._item) {
|
||||
component._item.keepOpen = keepOpen;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the theme for a context menu item.
|
||||
*
|
||||
* This method is supposed to be called when the context menu item is closed,
|
||||
* so there is no need for triggering a re-render eagarly.
|
||||
*
|
||||
* @param {HTMLElement} component
|
||||
* @param {string | undefined | null} theme
|
||||
*/
|
||||
function setTheme(component, theme) {
|
||||
if (component._item) {
|
||||
component._item.theme = theme;
|
||||
}
|
||||
}
|
||||
|
||||
window.Vaadin.Flow.contextMenuConnector = {
|
||||
initLazy,
|
||||
generateItemsTree,
|
||||
setChecked,
|
||||
setKeepOpen,
|
||||
setTheme
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
import * as Gestures from '@vaadin/component-base/src/gestures.js';
|
||||
|
||||
function init(target) {
|
||||
if (target.$contextMenuTargetConnector) {
|
||||
return;
|
||||
}
|
||||
|
||||
target.$contextMenuTargetConnector = {
|
||||
openOnHandler(e) {
|
||||
// used by Grid to prevent context menu on selection column click
|
||||
if (target.preventContextMenu && target.preventContextMenu(e)) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.$contextMenuTargetConnector.openEvent = e;
|
||||
let detail = {};
|
||||
if (target.getContextMenuBeforeOpenDetail) {
|
||||
detail = target.getContextMenuBeforeOpenDetail(e);
|
||||
}
|
||||
target.dispatchEvent(
|
||||
new CustomEvent('vaadin-context-menu-before-open', {
|
||||
detail: detail
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
updateOpenOn(eventType) {
|
||||
this.removeListener();
|
||||
this.openOnEventType = eventType;
|
||||
|
||||
customElements.whenDefined('vaadin-context-menu').then(() => {
|
||||
if (Gestures.gestures[eventType]) {
|
||||
Gestures.addListener(target, eventType, this.openOnHandler);
|
||||
} else {
|
||||
target.addEventListener(eventType, this.openOnHandler);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeListener() {
|
||||
if (this.openOnEventType) {
|
||||
if (Gestures.gestures[this.openOnEventType]) {
|
||||
Gestures.removeListener(target, this.openOnEventType, this.openOnHandler);
|
||||
} else {
|
||||
target.removeEventListener(this.openOnEventType, this.openOnHandler);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
openMenu(contextMenu) {
|
||||
contextMenu.open(this.openEvent);
|
||||
},
|
||||
|
||||
removeConnector() {
|
||||
this.removeListener();
|
||||
target.$contextMenuTargetConnector = undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
window.Vaadin.Flow.contextMenuTargetConnector = { init };
|
||||
1
src/main/frontend/generated/jar-resources/copilot.css
Normal file
1
src/main/frontend/generated/jar-resources/copilot.css
Normal file
File diff suppressed because one or more lines are too long
3
src/main/frontend/generated/jar-resources/copilot.d.ts
vendored
Normal file
3
src/main/frontend/generated/jar-resources/copilot.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export { _registerImporter } from './copilot/figma-public/figma-api';
|
||||
export type { FigmaNode } from './copilot/figma-public/figma-api';
|
||||
export type { ComponentDefinition, ComponentDefinitionProperties } from './copilot/shared/flow-utils';
|
||||
4
src/main/frontend/generated/jar-resources/copilot.js
Normal file
4
src/main/frontend/generated/jar-resources/copilot.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import { as as o } from "./copilot/copilot-CP3-W7yE.js";
|
||||
export {
|
||||
o as _registerImporter
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import { v as t, j as n, b as a } from "./copilot-CP3-W7yE.js";
|
||||
class i extends t {
|
||||
constructor() {
|
||||
super(...arguments), this.eventBusRemovers = [], this.messageHandlers = {}, this.handleESC = (e) => {
|
||||
n.active && e.key === "Escape" && typeof this.close == "function" && this.close();
|
||||
};
|
||||
}
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
onEventBus(e, s) {
|
||||
this.eventBusRemovers.push(a.on(e, s));
|
||||
}
|
||||
connectedCallback() {
|
||||
super.connectedCallback(), this.addESCListener();
|
||||
}
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback(), this.eventBusRemovers.forEach((e) => e()), this.removeESCListener();
|
||||
}
|
||||
addESCListener() {
|
||||
document.addEventListener("keydown", this.handleESC);
|
||||
}
|
||||
removeESCListener() {
|
||||
document.removeEventListener("keydown", this.handleESC);
|
||||
}
|
||||
onCommand(e, s) {
|
||||
this.messageHandlers[e] = s;
|
||||
}
|
||||
handleMessage(e) {
|
||||
return this.messageHandlers[e.command] ? (this.messageHandlers[e.command].call(this, e), !0) : !1;
|
||||
}
|
||||
}
|
||||
export {
|
||||
i as B
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,70 @@
|
||||
import { j as d, F as r, a2 as c, am as g, af as f, an as u, U as h, M as m, ao as v, u as b } from "./copilot-CP3-W7yE.js";
|
||||
import { B as $ } from "./base-panel-Ckfoxxex.js";
|
||||
import { i as w } from "./icons-DVw-r69H.js";
|
||||
const x = "copilot-features-panel{padding:var(--space-100);font:var(--font-xsmall);display:grid;grid-template-columns:auto 1fr;gap:var(--space-50);height:auto}copilot-features-panel a{display:flex;align-items:center;gap:var(--space-50);white-space:nowrap}copilot-features-panel a svg{height:12px;width:12px;min-height:12px;min-width:12px}";
|
||||
var F = Object.getOwnPropertyDescriptor, y = (e, a, o, s) => {
|
||||
for (var t = s > 1 ? void 0 : s ? F(a, o) : a, l = e.length - 1, i; l >= 0; l--)
|
||||
(i = e[l]) && (t = i(t) || t);
|
||||
return t;
|
||||
};
|
||||
const n = window.Vaadin.devTools;
|
||||
let p = class extends $ {
|
||||
render() {
|
||||
return r` <style>
|
||||
${x}
|
||||
</style>
|
||||
${d.featureFlags.map(
|
||||
(e) => r`
|
||||
<copilot-toggle-button
|
||||
.title="${e.title}"
|
||||
?checked=${e.enabled}
|
||||
@on-change=${(a) => this.toggleFeatureFlag(a, e)}>
|
||||
</copilot-toggle-button>
|
||||
<a class="ahreflike" href="${e.moreInfoLink}" title="Learn more" target="_blank"
|
||||
>learn more ${w.share}</a
|
||||
>
|
||||
`
|
||||
)}`;
|
||||
}
|
||||
toggleFeatureFlag(e, a) {
|
||||
const o = e.target.checked;
|
||||
if (c("use-feature", { source: "toggle", enabled: o, id: a.id }), n.frontendConnection) {
|
||||
n.frontendConnection.send("setFeature", { featureId: a.id, enabled: o });
|
||||
let s;
|
||||
if (a.requiresServerRestart) {
|
||||
const t = "This feature requires a server restart";
|
||||
g() ? s = f(
|
||||
r`${t} <br />
|
||||
${u()}`
|
||||
) : s = t;
|
||||
}
|
||||
h({
|
||||
type: m.INFORMATION,
|
||||
message: `“${a.title}” ${o ? "enabled" : "disabled"}`,
|
||||
details: s,
|
||||
dismissId: `feature${a.id}${o ? "Enabled" : "Disabled"}`
|
||||
}), v();
|
||||
} else
|
||||
n.log("error", `Unable to toggle feature ${a.title}: No server connection available`);
|
||||
}
|
||||
};
|
||||
p = y([
|
||||
b("copilot-features-panel")
|
||||
], p);
|
||||
const I = {
|
||||
header: "Features",
|
||||
expanded: !1,
|
||||
panelOrder: 35,
|
||||
panel: "right",
|
||||
floating: !1,
|
||||
tag: "copilot-features-panel",
|
||||
helpUrl: "https://vaadin.com/docs/latest/flow/configuration/feature-flags"
|
||||
}, O = {
|
||||
init(e) {
|
||||
e.addPanel(I);
|
||||
}
|
||||
};
|
||||
window.Vaadin.copilot.plugins.push(O);
|
||||
export {
|
||||
p as CopilotFeaturesPanel
|
||||
};
|
||||
@@ -0,0 +1,217 @@
|
||||
import { F as c, j as d, b as h, x as g, a2 as u, s as v, P as f, H as m, u as k } from "./copilot-CP3-W7yE.js";
|
||||
import { r as s } from "./state-C3WY-pqX.js";
|
||||
import { m as w, e as $ } from "./overlay-monkeypatch-DEOgVcvl.js";
|
||||
import { B as x } from "./base-panel-Ckfoxxex.js";
|
||||
import { i as A } from "./icons-DVw-r69H.js";
|
||||
const P = "copilot-feedback-panel{display:flex;flex-direction:column;font:var(--font-xsmall);gap:var(--space-200);padding:var(--space-150)}copilot-feedback-panel>p{margin:0}copilot-feedback-panel .dialog-footer{display:flex;gap:var(--space-100)}copilot-feedback-panel :is(vaadin-select,vaadin-text-area,vaadin-email-field){padding:0}copilot-feedback-panel :is(vaadin-select,vaadin-text-area,vaadin-email-field)::part(input-field),copilot-feedback-panel vaadin-select-value-button{padding:0}copilot-feedback-panel vaadin-select::part(toggle-button){align-items:center;display:flex;height:var(--size-m);justify-content:center;width:var(--size-m)}copilot-feedback-panel vaadin-text-area textarea{line-height:var(--line-height-1);padding:calc((var(--size-m) - var(--line-height-1)) / 2) var(--space-100)}copilot-feedback-panel vaadin-text-area:hover::part(input-field){background:none}copilot-feedback-panel vaadin-email-field input{padding:0 var(--space-100)}copilot-feedback-panel>*::part(label){font-weight:var(--font-weight-medium);line-height:var(--line-height-1);margin:0;padding:0 var(--space-150) var(--space-50) 0}copilot-feedback-panel>*::part(helper-text){line-height:var(--line-height-1);margin:0}";
|
||||
var F = Object.defineProperty, T = Object.getOwnPropertyDescriptor, o = (e, t, n, l) => {
|
||||
for (var a = l > 1 ? void 0 : l ? T(t, n) : t, p = e.length - 1, r; p >= 0; p--)
|
||||
(r = e[p]) && (a = (l ? r(t, n, a) : r(a)) || a);
|
||||
return l && a && F(t, n, a), a;
|
||||
};
|
||||
const D = "https://github.com/vaadin", b = "https://github.com/vaadin/copilot/issues/new", E = "?template=feature_request.md&title=%5BFEATURE%5D", U = "A short, concise description of the bug and why you consider it a bug. Any details like exceptions and logs can be helpful as well.", C = "Please provide as many details as possible, this will help us deliver a fix as soon as possible.%0AThank you!%0A%0A%23%23%23 Description of the Bug%0A%0A{description}%0A%0A%23%23%23 Expected Behavior%0A%0AA description of what you would expect to happen. (Sometimes it is clear what the expected outcome is if something does not work, other times, it is not super clear.)%0A%0A%23%23%23 Minimal Reproducible Example%0A%0AWe would appreciate the minimum code with which we can reproduce the issue.%0A%0A%23%23%23 Versions%0A{versionsInfo}";
|
||||
let i = class extends x {
|
||||
constructor() {
|
||||
super(), this.description = "", this.types = [
|
||||
{
|
||||
label: "Generic feedback",
|
||||
value: "feedback",
|
||||
ghTitle: ""
|
||||
},
|
||||
{
|
||||
label: "Report a bug",
|
||||
value: "bug",
|
||||
ghTitle: "[BUG]"
|
||||
},
|
||||
{
|
||||
label: "Ask a question",
|
||||
value: "question",
|
||||
ghTitle: "[QUESTION]"
|
||||
},
|
||||
{
|
||||
label: "Share an idea",
|
||||
value: "idea",
|
||||
ghTitle: "[FEATURE]"
|
||||
}
|
||||
], this.type = this.types[0].value, this.topics = [
|
||||
{
|
||||
label: "Generic",
|
||||
value: "platform"
|
||||
},
|
||||
{
|
||||
label: "Flow",
|
||||
value: "flow"
|
||||
},
|
||||
{
|
||||
label: "Hilla",
|
||||
value: "hilla"
|
||||
},
|
||||
{
|
||||
label: "Copilot",
|
||||
value: "copilot"
|
||||
}
|
||||
], this.topic = this.topics[0].value;
|
||||
}
|
||||
render() {
|
||||
return c`<style>
|
||||
${P}</style
|
||||
>${this.renderContent()}${this.renderFooter()}`;
|
||||
}
|
||||
firstUpdated() {
|
||||
w(this);
|
||||
}
|
||||
renderContent() {
|
||||
return this.message === void 0 ? c`
|
||||
<p>
|
||||
Your insights are incredibly valuable to us. Whether you’ve encountered a hiccup, have questions, or ideas
|
||||
to make our platform better, we're all ears! If you wish, leave your email, and we’ll get back to you. You
|
||||
can even share your code snippet with us for a clearer picture.
|
||||
</p>
|
||||
<vaadin-select
|
||||
.items="${this.types}"
|
||||
.value="${this.type}"
|
||||
overlay-class="alwaysVisible"
|
||||
@value-changed=${(e) => {
|
||||
this.type = e.detail.value;
|
||||
}}>
|
||||
</vaadin-select>
|
||||
<vaadin-select
|
||||
label="Feedback Topic"
|
||||
overlay-class="alwaysVisible"
|
||||
.items=${this.topics}
|
||||
.value="${this.topic}"
|
||||
.hidden=${this.type !== "feedback"}
|
||||
@value-changed=${(e) => {
|
||||
this.topic = e.detail.value;
|
||||
}}>
|
||||
</vaadin-select>
|
||||
<vaadin-text-area
|
||||
.value="${this.description}"
|
||||
@keydown=${this.keyDown}
|
||||
@focus=${() => {
|
||||
this.descriptionField.invalid = !1, this.descriptionField.placeholder = "";
|
||||
}}
|
||||
@value-changed=${(e) => {
|
||||
this.description = e.detail.value;
|
||||
}}
|
||||
label="Tell Us More"
|
||||
helper-text="Describe what you're experiencing, wondering about, or envisioning. The more you share, the better we can understand and act on your feedback"></vaadin-text-area>
|
||||
<vaadin-text-field
|
||||
@keydown=${this.keyDown}
|
||||
@value-changed=${(e) => {
|
||||
this.email = e.detail.value;
|
||||
}}
|
||||
.required=${this.type === "question"}
|
||||
id="email"
|
||||
value="${d.userInfo?.email}"
|
||||
label="Your Email${this.type === "question" ? "" : " (Optional)"}"
|
||||
helper-text="Leave your email if you’d like us to follow up, we’d love to keep the conversation going."></vaadin-text-field>
|
||||
` : c`<p>${this.message}</p>`;
|
||||
}
|
||||
renderFooter() {
|
||||
return this.message === void 0 ? c`
|
||||
<div class="dialog-footer">
|
||||
<button
|
||||
style="margin-inline-end: auto"
|
||||
@click="${() => {
|
||||
d.active ? h.emit("system-info-with-callback", {
|
||||
callback: (e) => this.openGithub(e, this),
|
||||
notify: !1
|
||||
}) : this.openGithub(null, this);
|
||||
}}">
|
||||
<span class="prefix">${A.github}</span>
|
||||
Create GitHub Issue
|
||||
</button>
|
||||
<button @click="${this.close}">Cancel</button>
|
||||
<button class="primary" @click="${this.submit}" .disabled=${this.type === "question" && !this.email}>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
` : c` <div class="footer">
|
||||
<vaadin-button @click="${this.close}">Close</vaadin-button>
|
||||
</div>`;
|
||||
}
|
||||
close() {
|
||||
g.updatePanel("copilot-feedback-panel", {
|
||||
floating: !1
|
||||
});
|
||||
}
|
||||
submit() {
|
||||
if (u("feedback", { github: !1, type: this.type, topic: this.topic }), this.description.trim() === "") {
|
||||
this.descriptionField.invalid = !0, this.descriptionField.placeholder = "Please tell us more before sending", this.descriptionField.value = "";
|
||||
return;
|
||||
}
|
||||
const e = {
|
||||
description: this.description,
|
||||
email: this.email,
|
||||
type: this.type,
|
||||
topic: this.topic
|
||||
};
|
||||
d.active ? h.emit("system-info-with-callback", {
|
||||
callback: (t) => v(`${f}feedback`, { ...e, versions: t }),
|
||||
notify: !1
|
||||
}) : v(`${f}feedback`, { ...e, versions: {} }), this.parentNode?.style.setProperty("--section-height", "150px"), this.message = "Thank you for sharing feedback.";
|
||||
}
|
||||
keyDown(e) {
|
||||
(e.key === "Backspace" || e.key === "Delete") && e.stopPropagation();
|
||||
}
|
||||
openGithub(e, t) {
|
||||
if (u("feedback", { github: !0, type: this.type, topic: this.topic }), this.type === "idea") {
|
||||
window.open(`${b}${E}`);
|
||||
return;
|
||||
}
|
||||
if (this.type === "feedback") {
|
||||
window.open(`${D}/${this.topic}/issues/new`);
|
||||
return;
|
||||
}
|
||||
const n = e ? e.replace(/\n/g, "%0A") : "Activate Copilot to include version info.", l = `${t.types.find((r) => r.value === this.type)?.ghTitle}`, a = t.description !== "" ? t.description : U, p = C.replace("{description}", a).replace("{versionsInfo}", n);
|
||||
window.open(`${b}?title=${l}&body=${p}`, "_blank")?.focus();
|
||||
}
|
||||
};
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "description", 2);
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "type", 2);
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "topic", 2);
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "email", 2);
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "message", 2);
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "types", 2);
|
||||
o([
|
||||
s()
|
||||
], i.prototype, "topics", 2);
|
||||
o([
|
||||
$("vaadin-text-area")
|
||||
], i.prototype, "descriptionField", 2);
|
||||
i = o([
|
||||
k("copilot-feedback-panel")
|
||||
], i);
|
||||
const y = m({
|
||||
header: "Help Us Improve!",
|
||||
tag: "copilot-feedback-panel",
|
||||
width: 500,
|
||||
height: 550,
|
||||
floatingPosition: {
|
||||
top: 100,
|
||||
left: 100
|
||||
},
|
||||
individual: !0
|
||||
}), q = {
|
||||
init(e) {
|
||||
e.addPanel(y);
|
||||
}
|
||||
};
|
||||
window.Vaadin.copilot.plugins.push(q);
|
||||
g.addPanel(y);
|
||||
export {
|
||||
i as CopilotFeedbackPanel
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,205 @@
|
||||
import { ak as I, J as g, a2 as $, L as k, j as p, x as S, F as a, E, al as c, Q as C, W as V, U as P, M as D, v as A, b as H, u as w } from "./copilot-CP3-W7yE.js";
|
||||
import { r as x } from "./state-C3WY-pqX.js";
|
||||
import { B as T } from "./base-panel-Ckfoxxex.js";
|
||||
import { i as d } from "./icons-DVw-r69H.js";
|
||||
import { e as h, c as O } from "./early-project-state-DgrvrTky.js";
|
||||
const j = 'copilot-info-panel{--dev-tools-red-color: red;--dev-tools-grey-color: gray;--dev-tools-green-color: green;position:relative}copilot-info-panel dl{margin:0;width:100%}copilot-info-panel dl>div{align-items:center;display:flex;gap:var(--space-50);height:var(--size-m);padding:0 var(--space-150);position:relative}copilot-info-panel dl>div:after{border-bottom:1px solid var(--divider-secondary-color);content:"";inset:auto var(--space-150) 0;position:absolute}copilot-info-panel dl dt{color:var(--secondary-text-color)}copilot-info-panel dl dd{align-items:center;display:flex;font-weight:var(--font-weight-medium);gap:var(--space-50);margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}copilot-info-panel dl dd span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}copilot-info-panel dl dd span.icon{display:inline-flex;vertical-align:bottom}copilot-info-panel dd.live-reload-status>span{overflow:hidden;text-overflow:ellipsis;display:block;color:var(--status-color)}copilot-info-panel dd span.hidden{display:none}copilot-info-panel code{white-space:nowrap;-webkit-user-select:all;user-select:all}copilot-info-panel .checks{display:inline-grid;grid-template-columns:auto 1fr;gap:var(--space-50)}copilot-info-panel span.hint{font-size:var(--font-size-0);background:var(--gray-50);padding:var(--space-75);border-radius:var(--radius-2)}';
|
||||
var J = Object.defineProperty, N = Object.getOwnPropertyDescriptor, v = (e, t, n, i) => {
|
||||
for (var o = i > 1 ? void 0 : i ? N(t, n) : t, s = e.length - 1, l; s >= 0; s--)
|
||||
(l = e[s]) && (o = (i ? l(t, n, o) : l(o)) || o);
|
||||
return i && o && J(t, n, o), o;
|
||||
};
|
||||
let u = class extends T {
|
||||
constructor() {
|
||||
super(...arguments), this.serverInfo = [], this.clientInfo = [{ name: "Browser", version: navigator.userAgent }], this.handleServerInfoEvent = (e) => {
|
||||
const t = JSON.parse(e.data.info);
|
||||
this.serverInfo = t.versions, I().then((n) => {
|
||||
n && (this.clientInfo.unshift({ name: "Vaadin Employee", version: "true", more: void 0 }), this.requestUpdate("clientInfo"));
|
||||
}), g() === "success" && $("hotswap-active", { value: k() });
|
||||
};
|
||||
}
|
||||
connectedCallback() {
|
||||
super.connectedCallback(), this.onCommand("copilot-info", this.handleServerInfoEvent), this.onEventBus("system-info-with-callback", (e) => {
|
||||
e.detail.callback(this.getInfoForClipboard(e.detail.notify));
|
||||
}), this.reaction(
|
||||
() => p.idePluginState,
|
||||
() => {
|
||||
this.requestUpdate("serverInfo");
|
||||
}
|
||||
);
|
||||
}
|
||||
getIndex(e) {
|
||||
return this.serverInfo.findIndex((t) => t.name === e);
|
||||
}
|
||||
render() {
|
||||
const e = p.newVaadinVersionState?.versions !== void 0 && p.newVaadinVersionState.versions.length > 0, t = [...this.serverInfo, ...this.clientInfo];
|
||||
let n = this.getIndex("Spring") + 1;
|
||||
n === 0 && (n = t.length), h.springSecurityEnabled && (t.splice(n, 0, { name: "Spring Security", version: "true" }), n++), h.springJpaDataEnabled && (t.splice(n, 0, { name: "Spring Data JPA", version: "true" }), n++);
|
||||
const i = t.find((o) => o.name === "Vaadin");
|
||||
return i && (i.more = a` <button
|
||||
aria-label="Edit Vaadin Version"
|
||||
class="icon relative"
|
||||
id="new-vaadin-version-btn"
|
||||
title="Edit Vaadin Version"
|
||||
@click="${(o) => {
|
||||
o.stopPropagation(), S.updatePanel("copilot-vaadin-versions", { floating: !0 });
|
||||
}}">
|
||||
${d.editAlt}
|
||||
${e ? a`<span aria-hidden="true" class="absolute bg-error end-0 h-75 rounded-full top-0 w-75"></span>` : ""}
|
||||
</button>`), a` <style>
|
||||
${j}
|
||||
</style>
|
||||
<div class="flex flex-col gap-150 items-start">
|
||||
<dl>
|
||||
${t.map(
|
||||
(o) => a`
|
||||
<div>
|
||||
<dt>${o.name}</dt>
|
||||
<dd title="${o.version}">
|
||||
<span> ${this.renderValue(o.version)} </span>
|
||||
${o.more}
|
||||
</dd>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
${this.renderDevWorkflowSection()}
|
||||
</dl>
|
||||
${this.renderDevelopmentWorkflowButton()}
|
||||
</div>`;
|
||||
}
|
||||
renderDevWorkflowSection() {
|
||||
const e = g(), t = this.getIdePluginLabelText(p.idePluginState), n = this.getHotswapAgentLabelText(e);
|
||||
return a`
|
||||
<div>
|
||||
<dt>Java Hotswap</dt>
|
||||
<dd>
|
||||
${f(e === "success", e === "success" ? "Enabled" : "Disabled")} ${n}
|
||||
</dd>
|
||||
</div>
|
||||
${c() !== "unsupported" ? a` <div>
|
||||
<dt>IDE Plugin</dt>
|
||||
<dd>
|
||||
${f(
|
||||
c() === "success",
|
||||
c() === "success" ? "Installed" : "Not Installed"
|
||||
)}
|
||||
${t}
|
||||
</dd>
|
||||
</div>` : E}
|
||||
`;
|
||||
}
|
||||
renderDevelopmentWorkflowButton() {
|
||||
const e = C();
|
||||
let t = "", n = null, i = "";
|
||||
return e.status === "success" ? (t = "success", n = d.check, i = "Details") : e.status === "warning" ? (t = "warning", n = d.lightning, i = "Improve Development Workflow") : e.status === "error" && (t = "error", n = d.alertCircle, i = "Fix Development Workflow"), a`
|
||||
<button
|
||||
class="mx-50"
|
||||
id="development-workflow-guide"
|
||||
@click="${() => {
|
||||
V();
|
||||
}}">
|
||||
<span class="prefix ${t}-text"> ${n} </span>
|
||||
${i}
|
||||
<span class="suffix">
|
||||
<span class="bg-${t} end-0 h-75 rounded-full top-0 w-75"></span>
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
getHotswapAgentLabelText(e) {
|
||||
return e === "success" ? "Java Hotswap is enabled" : e === "error" ? "Hotswap is partially enabled" : "Hotswap is disabled";
|
||||
}
|
||||
getIdePluginLabelText(e) {
|
||||
if (c() !== "success")
|
||||
return "Not installed";
|
||||
if (e?.version) {
|
||||
let t = null;
|
||||
return e?.ide && (e?.ide === "intellij" ? t = "IntelliJ" : e?.ide === "vscode" ? t = "VS Code" : e?.ide === "eclipse" && (t = "Eclipse")), t ? `${e?.version} ${t}` : e?.version;
|
||||
}
|
||||
return "Not installed";
|
||||
}
|
||||
renderValue(e) {
|
||||
return e === "false" ? f(!1, "False") : e === "true" ? f(!0, "True") : e;
|
||||
}
|
||||
getInfoForClipboard(e) {
|
||||
const t = this.renderRoot.querySelectorAll(".items-start dt"), o = Array.from(t).map((s) => ({
|
||||
key: s.textContent.trim(),
|
||||
value: s.nextElementSibling.textContent.trim()
|
||||
})).filter((s) => s.key !== "Live reload").filter((s) => !s.key.startsWith("Vaadin Emplo")).map((s) => {
|
||||
const { key: l } = s;
|
||||
let { value: r } = s;
|
||||
if (l === "IDE Plugin")
|
||||
r = this.getIdePluginLabelText(p.idePluginState) ?? "false";
|
||||
else if (l === "Java Hotswap") {
|
||||
const y = p.jdkInfo?.jrebel, m = g();
|
||||
y && m === "success" ? r = "JRebel is in use" : r = this.getHotswapAgentLabelText(m);
|
||||
} else l === "Vaadin" && r.indexOf(`
|
||||
`) !== -1 && (r = r.substring(0, r.indexOf(`
|
||||
`)));
|
||||
return `${l}: ${r}`;
|
||||
}).join(`
|
||||
`);
|
||||
return e && P({
|
||||
type: D.INFORMATION,
|
||||
message: "Environment information copied to clipboard",
|
||||
dismissId: "versionInfoCopied"
|
||||
}), o.trim();
|
||||
}
|
||||
};
|
||||
v([
|
||||
x()
|
||||
], u.prototype, "serverInfo", 2);
|
||||
v([
|
||||
x()
|
||||
], u.prototype, "clientInfo", 2);
|
||||
u = v([
|
||||
w("copilot-info-panel")
|
||||
], u);
|
||||
let b = class extends A {
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
connectedCallback() {
|
||||
super.connectedCallback(), this.style.display = "flex";
|
||||
}
|
||||
render() {
|
||||
return a` <button
|
||||
@click=${() => {
|
||||
H.emit("system-info-with-callback", {
|
||||
callback: O,
|
||||
notify: !0
|
||||
});
|
||||
}}
|
||||
aria-label="Copy to Clipboard"
|
||||
class="icon"
|
||||
title="Copy to Clipboard">
|
||||
<span>${d.copy}</span>
|
||||
</button>`;
|
||||
}
|
||||
};
|
||||
b = v([
|
||||
w("copilot-info-actions")
|
||||
], b);
|
||||
const B = {
|
||||
header: "Info",
|
||||
expanded: !1,
|
||||
panelOrder: 15,
|
||||
panel: "right",
|
||||
floating: !1,
|
||||
tag: "copilot-info-panel",
|
||||
actionsTag: "copilot-info-actions",
|
||||
eager: !0
|
||||
// Render even when collapsed as error handling depends on this
|
||||
}, W = {
|
||||
init(e) {
|
||||
e.addPanel(B);
|
||||
}
|
||||
};
|
||||
window.Vaadin.copilot.plugins.push(W);
|
||||
function f(e, t) {
|
||||
return e ? a`<span aria-label=${t} class="icon success-text" title=${t}>${d.check}</span>` : a`<span aria-label=${t} class="icon error-text" title=${t}>${d.x}</span>`;
|
||||
}
|
||||
export {
|
||||
b as Actions,
|
||||
u as CopilotInfoPanel
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
||||
import { j as R, ah as S, ai as x, a6 as c, F as n, M as p, aj as M, a2 as L, v as D, b as k, K as I, m as q, x as A, u as v } from "./copilot-CP3-W7yE.js";
|
||||
import { r as $ } from "./state-C3WY-pqX.js";
|
||||
import { B as P } from "./base-panel-Ckfoxxex.js";
|
||||
import { i as l } from "./icons-DVw-r69H.js";
|
||||
const B = 'copilot-log-panel ul{list-style-type:none;margin:0;padding:0}copilot-log-panel ul li{align-items:start;display:flex;gap:var(--space-50);padding:var(--space-100) var(--space-50);position:relative}copilot-log-panel ul li:before{border-bottom:1px dashed var(--divider-primary-color);content:"";inset:auto 0 0 calc(var(--size-m) + var(--space-100));position:absolute}copilot-log-panel ul li span.icon{display:flex;flex-shrink:0;justify-content:center;width:var(--size-m)}copilot-log-panel ul li.information span.icon{color:var(--blue-color)}copilot-log-panel ul li.warning span.icon{color:var(--warning-color)}copilot-log-panel ul li.error span.icon{color:var(--error-color)}copilot-log-panel ul li .message{display:flex;flex-direction:column;flex-grow:1;overflow:hidden}copilot-log-panel ul li:not(.expanded) span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}copilot-log-panel ul li button svg{transition:transform .15s cubic-bezier(.2,0,0,1)}copilot-log-panel ul li button[aria-expanded=true] svg{transform:rotate(90deg)}copilot-log-panel ul li code{margin-top:var(--space-50)}copilot-log-panel ul li.expanded .secondary{margin-top:var(--space-100)}copilot-log-panel .secondary a{display:block;margin-bottom:var(--space-50)}';
|
||||
var C = Object.defineProperty, _ = Object.getOwnPropertyDescriptor, u = (e, t, a, i) => {
|
||||
for (var o = i > 1 ? void 0 : i ? _(t, a) : t, d = e.length - 1, s; d >= 0; d--)
|
||||
(s = e[d]) && (o = (i ? s(t, a, o) : s(o)) || o);
|
||||
return i && o && C(t, a, o), o;
|
||||
};
|
||||
class b {
|
||||
constructor() {
|
||||
this.showTimestamps = !1, q(this);
|
||||
}
|
||||
toggleShowTimestamps() {
|
||||
this.showTimestamps = !this.showTimestamps;
|
||||
}
|
||||
}
|
||||
const h = new b();
|
||||
let r = class extends P {
|
||||
constructor() {
|
||||
super(...arguments), this.unreadErrors = !1, this.messages = [], this.nextMessageId = 1, this.transitionDuration = 0, this.errorHandlersAdded = !1;
|
||||
}
|
||||
connectedCallback() {
|
||||
if (super.connectedCallback(), this.onCommand("log", (e) => {
|
||||
this.handleLogEventData({ type: e.data.type, message: e.data.message });
|
||||
}), this.onEventBus("log", (e) => this.handleLogEvent(e)), this.onEventBus("update-log", (e) => this.updateLog(e.detail)), this.onEventBus("notification-shown", (e) => this.handleNotification(e)), this.onEventBus("clear-log", () => this.clear()), this.reaction(
|
||||
() => R.sectionPanelResizing,
|
||||
() => {
|
||||
this.requestUpdate();
|
||||
}
|
||||
), this.transitionDuration = parseInt(
|
||||
window.getComputedStyle(this).getPropertyValue("--dev-tools-transition-duration"),
|
||||
10
|
||||
), !this.errorHandlersAdded) {
|
||||
const e = (t) => {
|
||||
I(() => {
|
||||
A.attentionRequiredPanelTag = "copilot-log-panel";
|
||||
}), this.log(p.ERROR, t.message, !!t.internal, t.details, t.link);
|
||||
};
|
||||
S((t) => {
|
||||
e(t);
|
||||
}), x.forEach((t) => {
|
||||
e(t);
|
||||
}), x.length = 0, this.errorHandlersAdded = !0;
|
||||
}
|
||||
}
|
||||
clear() {
|
||||
this.messages = [];
|
||||
}
|
||||
handleNotification(e) {
|
||||
this.log(e.detail.type, e.detail.message, !0, e.detail.details, e.detail.link);
|
||||
}
|
||||
handleLogEvent(e) {
|
||||
this.handleLogEventData(e.detail);
|
||||
}
|
||||
handleLogEventData(e) {
|
||||
this.log(
|
||||
e.type,
|
||||
e.message,
|
||||
!!e.internal,
|
||||
e.details,
|
||||
e.link,
|
||||
c(e.expandedMessage),
|
||||
c(e.expandedDetails),
|
||||
e.id
|
||||
);
|
||||
}
|
||||
activate() {
|
||||
this.unreadErrors = !1, this.updateComplete.then(() => {
|
||||
const e = this.renderRoot.querySelector(".message:last-child");
|
||||
e && e.scrollIntoView();
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return n`
|
||||
<style>
|
||||
${B}
|
||||
</style>
|
||||
<ul>
|
||||
${this.messages.map((e) => this.renderMessage(e))}
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
renderMessage(e) {
|
||||
let t, a;
|
||||
return e.type === p.ERROR ? (a = l.alertTriangle, t = "Error") : e.type === p.WARNING ? (a = l.warning, t = "Warning") : (a = l.info, t = "Info"), n`
|
||||
<li
|
||||
class="${e.type} ${e.expanded ? "expanded" : ""} ${e.details || e.link ? "has-details" : ""}"
|
||||
data-id="${e.id}">
|
||||
<span aria-label="${t}" class="icon" title="${t}">${a}</span>
|
||||
<span class="message" @click=${() => this.toggleExpanded(e)}>
|
||||
<span class="timestamp" ?hidden=${!h.showTimestamps}>${N(e.timestamp)}</span>
|
||||
<span class="primary">
|
||||
${e.expanded && e.expandedMessage ? e.expandedMessage : e.message}
|
||||
</span>
|
||||
${e.expanded ? n` <span class="secondary"> ${e.expandedDetails ?? e.details} </span>` : n` <span class="secondary" ?hidden="${!e.details && !e.link}">
|
||||
${c(e.details)}
|
||||
${e.link ? n` <a href="${e.link}" target="_blank">Learn more</a>` : ""}
|
||||
</span>`}
|
||||
</span>
|
||||
<!-- TODO: a11y, button needs aria-controls with unique ids -->
|
||||
<button
|
||||
aria-controls="content"
|
||||
aria-expanded="${e.expanded}"
|
||||
aria-label="Expand details"
|
||||
class="icon"
|
||||
@click=${() => this.toggleExpanded(e)}
|
||||
?hidden=${!this.canBeExpanded(e)}>
|
||||
<span>${l.chevronRight}</span>
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
log(e, t, a, i, o, d, s, E) {
|
||||
const T = this.nextMessageId;
|
||||
this.nextMessageId += 1, s || (s = t);
|
||||
const m = {
|
||||
id: T,
|
||||
type: e,
|
||||
message: t,
|
||||
details: i,
|
||||
link: o,
|
||||
dontShowAgain: !1,
|
||||
deleted: !1,
|
||||
expanded: !1,
|
||||
expandedMessage: d,
|
||||
expandedDetails: s,
|
||||
timestamp: /* @__PURE__ */ new Date(),
|
||||
internal: a,
|
||||
userId: E
|
||||
};
|
||||
for (this.messages.push(m); this.messages.length > r.MAX_LOG_ROWS; )
|
||||
this.messages.shift();
|
||||
return this.requestUpdate(), this.updateComplete.then(() => {
|
||||
const f = this.renderRoot.querySelector(".message:last-child");
|
||||
f ? (setTimeout(() => f.scrollIntoView({ behavior: "smooth" }), this.transitionDuration), this.unreadErrors = !1) : e === p.ERROR && (this.unreadErrors = !0);
|
||||
}), m;
|
||||
}
|
||||
updateLog(e) {
|
||||
let t = this.messages.find((a) => a.userId === e.id);
|
||||
t || (t = this.log(p.INFORMATION, "<Log message to update was not found>", !1)), Object.assign(t, e), M(t.expandedDetails) && (t.expandedDetails = c(t.expandedDetails)), this.requestUpdate();
|
||||
}
|
||||
updated() {
|
||||
const e = this.querySelector(".row:last-child");
|
||||
e && this.isTooLong(e.querySelector(".firstrowmessage")) && e.querySelector("button.expand")?.removeAttribute("hidden");
|
||||
}
|
||||
toggleExpanded(e) {
|
||||
this.canBeExpanded(e) && (e.expanded = !e.expanded, this.requestUpdate()), L("use-log", { source: "toggleExpanded" });
|
||||
}
|
||||
canBeExpanded(e) {
|
||||
if (e.expandedMessage || e.expanded)
|
||||
return !0;
|
||||
const t = this.querySelector(`[data\\-id="${e.id}"]`)?.querySelector(
|
||||
".firstrowmessage"
|
||||
);
|
||||
return this.isTooLong(t);
|
||||
}
|
||||
isTooLong(e) {
|
||||
return e && e.offsetWidth < e.scrollWidth;
|
||||
}
|
||||
};
|
||||
r.MAX_LOG_ROWS = 1e3;
|
||||
u([
|
||||
$()
|
||||
], r.prototype, "unreadErrors", 2);
|
||||
u([
|
||||
$()
|
||||
], r.prototype, "messages", 2);
|
||||
r = u([
|
||||
v("copilot-log-panel")
|
||||
], r);
|
||||
let y = class extends D {
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
render() {
|
||||
return n`
|
||||
<style>
|
||||
copilot-log-panel-actions {
|
||||
display: contents;
|
||||
}
|
||||
</style>
|
||||
<button
|
||||
aria-label="Clear log"
|
||||
class="icon"
|
||||
title="Clear log"
|
||||
@click=${() => {
|
||||
k.emit("clear-log", {});
|
||||
}}>
|
||||
<span>${l.trash}</span>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Toggle timestamps"
|
||||
class="icon"
|
||||
title="Toggle timestamps"
|
||||
@click=${() => {
|
||||
h.toggleShowTimestamps();
|
||||
}}>
|
||||
<span class="${h.showTimestamps ? "on" : "off"}"> ${l.clock} </span>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
};
|
||||
y = u([
|
||||
v("copilot-log-panel-actions")
|
||||
], y);
|
||||
const U = {
|
||||
header: "Log",
|
||||
expanded: !0,
|
||||
panelOrder: 0,
|
||||
panel: "bottom",
|
||||
floating: !1,
|
||||
tag: "copilot-log-panel",
|
||||
actionsTag: "copilot-log-panel-actions"
|
||||
}, F = {
|
||||
init(e) {
|
||||
e.addPanel(U);
|
||||
}
|
||||
};
|
||||
window.Vaadin.copilot.plugins.push(F);
|
||||
const w = { hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 3 };
|
||||
let g;
|
||||
try {
|
||||
g = new Intl.DateTimeFormat(navigator.language, w);
|
||||
} catch (e) {
|
||||
console.error("Failed to create date time formatter for ", navigator.language, e), g = new Intl.DateTimeFormat("en-US", w);
|
||||
}
|
||||
function N(e) {
|
||||
return g.format(e);
|
||||
}
|
||||
export {
|
||||
y as Actions,
|
||||
r as CopilotLogPanel
|
||||
};
|
||||
@@ -0,0 +1,127 @@
|
||||
import { u as f, b as c, E as g, F as i, a0 as b, X as s, H as m } from "./copilot-CP3-W7yE.js";
|
||||
import { B as $ } from "./base-panel-Ckfoxxex.js";
|
||||
import { i as e } from "./icons-DVw-r69H.js";
|
||||
const v = 'copilot-shortcuts-panel{display:flex;flex-direction:column;padding:var(--space-150)}copilot-shortcuts-panel h3{font:var(--font-xsmall-semibold);margin-bottom:var(--space-100);margin-top:0}copilot-shortcuts-panel h3:not(:first-of-type){margin-top:var(--space-200)}copilot-shortcuts-panel ul{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}copilot-shortcuts-panel ul li{display:flex;align-items:center;gap:var(--space-50);position:relative}copilot-shortcuts-panel ul li:not(:last-of-type):before{border-bottom:1px dashed var(--border-color);content:"";inset:auto 0 0 calc(var(--size-m) + var(--space-50));position:absolute}copilot-shortcuts-panel ul li span:has(svg){align-items:center;display:flex;height:var(--size-m);justify-content:center;width:var(--size-m)}copilot-shortcuts-panel .kbds{margin-inline-start:auto}copilot-shortcuts-panel kbd{align-items:center;border:1px solid var(--border-color);border-radius:var(--radius-2);box-sizing:border-box;display:inline-flex;font-family:var(--font-family);font-size:var(--font-size-1);line-height:var(--line-height-1);padding:0 var(--space-50)}', u = window.Vaadin.copilot.tree;
|
||||
if (!u)
|
||||
throw new Error("Tried to access copilot tree before it was initialized.");
|
||||
var y = Object.getOwnPropertyDescriptor, w = (t, l, h, p) => {
|
||||
for (var o = p > 1 ? void 0 : p ? y(l, h) : l, n = t.length - 1, r; n >= 0; n--)
|
||||
(r = t[n]) && (o = r(o) || o);
|
||||
return o;
|
||||
};
|
||||
let d = class extends $ {
|
||||
constructor() {
|
||||
super(), this.onTreeUpdated = () => {
|
||||
this.requestUpdate();
|
||||
};
|
||||
}
|
||||
connectedCallback() {
|
||||
super.connectedCallback(), c.on("copilot-tree-created", this.onTreeUpdated);
|
||||
}
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback(), c.off("copilot-tree-created", this.onTreeUpdated);
|
||||
}
|
||||
render() {
|
||||
const t = u.hasFlowComponents();
|
||||
return i`<style>
|
||||
${v}
|
||||
</style>
|
||||
<h3>Global</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<span>${e.vaadinLogo}</span>
|
||||
<span>Copilot</span>
|
||||
${a(s.toggleCopilot)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.terminal}</span>
|
||||
<span>Command window</span>
|
||||
${a(s.toggleCommandWindow)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.flipBack}</span>
|
||||
<span>Undo</span>
|
||||
${a(s.undo)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.flipForward}</span>
|
||||
<span>Redo</span>
|
||||
${a(s.redo)}
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Selected component</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<span>${e.fileCodeAlt}</span>
|
||||
<span>Go to source</span>
|
||||
${a(s.goToSource)}
|
||||
</li>
|
||||
${t ? i`<li>
|
||||
<span>${e.code}</span>
|
||||
<span>Go to attach source</span>
|
||||
${a(s.goToAttachSource)}
|
||||
</li>` : g}
|
||||
<li>
|
||||
<span>${e.copy}</span>
|
||||
<span>Copy</span>
|
||||
${a(s.copy)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.clipboard}</span>
|
||||
<span>Paste</span>
|
||||
${a(s.paste)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.copyAlt}</span>
|
||||
<span>Duplicate</span>
|
||||
${a(s.duplicate)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.userUp}</span>
|
||||
<span>Select parent</span>
|
||||
${a(s.selectParent)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.userLeft}</span>
|
||||
<span>Select previous sibling</span>
|
||||
${a(s.selectPreviousSibling)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.userRight}</span>
|
||||
<span>Select first child / next sibling</span>
|
||||
${a(s.selectNextSibling)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.trash}</span>
|
||||
<span>Delete</span>
|
||||
${a(s.delete)}
|
||||
</li>
|
||||
<li>
|
||||
<span>${e.zap}</span>
|
||||
<span>Quick add from palette</span>
|
||||
${a("<kbd>A ... Z</kbd>")}
|
||||
</li>
|
||||
</ul>`;
|
||||
}
|
||||
};
|
||||
d = w([
|
||||
f("copilot-shortcuts-panel")
|
||||
], d);
|
||||
function a(t) {
|
||||
return i`<span class="kbds">${b(t)}</span>`;
|
||||
}
|
||||
const x = m({
|
||||
header: "Keyboard Shortcuts",
|
||||
tag: "copilot-shortcuts-panel",
|
||||
width: 400,
|
||||
height: 550,
|
||||
floatingPosition: {
|
||||
top: 50,
|
||||
left: 50
|
||||
}
|
||||
}), C = {
|
||||
init(t) {
|
||||
t.addPanel(x);
|
||||
}
|
||||
};
|
||||
window.Vaadin.copilot.plugins.push(C);
|
||||
@@ -0,0 +1,80 @@
|
||||
import { a as D } from "./copilot-CP3-W7yE.js";
|
||||
var y, v;
|
||||
function E() {
|
||||
return v || (v = 1, y = function() {
|
||||
var a = document.getSelection();
|
||||
if (!a.rangeCount)
|
||||
return function() {
|
||||
};
|
||||
for (var o = document.activeElement, s = [], i = 0; i < a.rangeCount; i++)
|
||||
s.push(a.getRangeAt(i));
|
||||
switch (o.tagName.toUpperCase()) {
|
||||
// .toUpperCase handles XHTML
|
||||
case "INPUT":
|
||||
case "TEXTAREA":
|
||||
o.blur();
|
||||
break;
|
||||
default:
|
||||
o = null;
|
||||
break;
|
||||
}
|
||||
return a.removeAllRanges(), function() {
|
||||
a.type === "Caret" && a.removeAllRanges(), a.rangeCount || s.forEach(function(d) {
|
||||
a.addRange(d);
|
||||
}), o && o.focus();
|
||||
};
|
||||
}), y;
|
||||
}
|
||||
var g, C;
|
||||
function h() {
|
||||
if (C) return g;
|
||||
C = 1;
|
||||
var a = E(), o = {
|
||||
"text/plain": "Text",
|
||||
"text/html": "Url",
|
||||
default: "Text"
|
||||
}, s = "Copy to clipboard: #{key}, Enter";
|
||||
function i(n) {
|
||||
var t = (/mac os x/i.test(navigator.userAgent) ? "⌘" : "Ctrl") + "+C";
|
||||
return n.replace(/#{\s*key\s*}/g, t);
|
||||
}
|
||||
function d(n, t) {
|
||||
var c, m, b, u, l, e, f = !1;
|
||||
t || (t = {}), c = t.debug || !1;
|
||||
try {
|
||||
b = a(), u = document.createRange(), l = document.getSelection(), e = document.createElement("span"), e.textContent = n, e.ariaHidden = "true", e.style.all = "unset", e.style.position = "fixed", e.style.top = 0, e.style.clip = "rect(0, 0, 0, 0)", e.style.whiteSpace = "pre", e.style.webkitUserSelect = "text", e.style.MozUserSelect = "text", e.style.msUserSelect = "text", e.style.userSelect = "text", e.addEventListener("copy", function(r) {
|
||||
if (r.stopPropagation(), t.format)
|
||||
if (r.preventDefault(), typeof r.clipboardData > "u") {
|
||||
c && console.warn("unable to use e.clipboardData"), c && console.warn("trying IE specific stuff"), window.clipboardData.clearData();
|
||||
var p = o[t.format] || o.default;
|
||||
window.clipboardData.setData(p, n);
|
||||
} else
|
||||
r.clipboardData.clearData(), r.clipboardData.setData(t.format, n);
|
||||
t.onCopy && (r.preventDefault(), t.onCopy(r.clipboardData));
|
||||
}), document.body.appendChild(e), u.selectNodeContents(e), l.addRange(u);
|
||||
var w = document.execCommand("copy");
|
||||
if (!w)
|
||||
throw new Error("copy command was unsuccessful");
|
||||
f = !0;
|
||||
} catch (r) {
|
||||
c && console.error("unable to copy using execCommand: ", r), c && console.warn("trying IE specific stuff");
|
||||
try {
|
||||
window.clipboardData.setData(t.format || "text", n), t.onCopy && t.onCopy(window.clipboardData), f = !0;
|
||||
} catch (p) {
|
||||
c && console.error("unable to copy using clipboardData: ", p), c && console.error("falling back to prompt"), m = i("message" in t ? t.message : s), window.prompt(m, n);
|
||||
}
|
||||
} finally {
|
||||
l && (typeof l.removeRange == "function" ? l.removeRange(u) : l.removeAllRanges()), e && document.body.removeChild(e), b();
|
||||
}
|
||||
return f;
|
||||
}
|
||||
return g = d, g;
|
||||
}
|
||||
var x = h();
|
||||
const S = /* @__PURE__ */ D(x), T = window.Vaadin.copilot._earlyProjectState;
|
||||
if (!T)
|
||||
throw new Error("Tried to access early project state before it was initialized.");
|
||||
export {
|
||||
S as c,
|
||||
T as e
|
||||
};
|
||||
100
src/main/frontend/generated/jar-resources/copilot/figma-public/figma-api.d.ts
vendored
Normal file
100
src/main/frontend/generated/jar-resources/copilot/figma-public/figma-api.d.ts
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import { NodeType, StackAlign, StackCounterAlign, StackJustify, StackMode, StackSize } from 'fig-kiwi/fig-kiwi';
|
||||
import { ComponentDefinition } from '../shared/flow-utils';
|
||||
export type SwappedInstance = {
|
||||
name: string | undefined;
|
||||
symbolDescription: string | undefined;
|
||||
};
|
||||
export type PropertyValue = SwappedInstance | boolean | number | string;
|
||||
export type FigmaNode = {
|
||||
type: NodeType | undefined;
|
||||
name: string | undefined;
|
||||
symbolDescription: string | undefined;
|
||||
parent: FigmaNode | undefined;
|
||||
children: FigmaNode[];
|
||||
htmlTag: string;
|
||||
reactTag: string;
|
||||
vaadinComponent: boolean;
|
||||
vaadinLayout: boolean;
|
||||
width: number | undefined;
|
||||
height: number | undefined;
|
||||
x: number | undefined;
|
||||
y: number | undefined;
|
||||
classNames: string[];
|
||||
styles: Record<string, string>;
|
||||
properties: Record<string, PropertyValue>;
|
||||
relativePosition: boolean;
|
||||
stackMode: StackMode | undefined;
|
||||
stackSpacing: number | undefined;
|
||||
stackPrimaryAlignItems: StackJustify | undefined;
|
||||
stackCounterAlignItems: StackAlign | undefined;
|
||||
stackPrimarySizing: StackSize | undefined;
|
||||
stackCounterSizing: StackSize | undefined;
|
||||
stackChildAlignSelf: StackCounterAlign | undefined;
|
||||
stackChildPrimaryGrow: number | undefined;
|
||||
stackHorizontalPadding: number | undefined;
|
||||
stackVerticalPadding: number | undefined;
|
||||
stackPadding: number | undefined;
|
||||
stackPaddingBottom: number | undefined;
|
||||
stackPaddingRight: number | undefined;
|
||||
_innerHTML: string | undefined;
|
||||
};
|
||||
export type Importer = (node: FigmaNode, metadata: ImportMetadata) => ComponentDefinition | undefined;
|
||||
export type ImportMetadata = {
|
||||
target: 'java' | 'react';
|
||||
};
|
||||
/**
|
||||
* Registers a custom importer function that can be used to convert Figma nodes into Vaadin components.
|
||||
* <p>
|
||||
* For example if you have a figma component called "AcmeCard" with a marker property `type=AcmeCard` and with two properties for customizing it: title and content,
|
||||
* you can register an importer like this:
|
||||
*
|
||||
* ```typescript
|
||||
* import type { ComponentDefinition, FigmaNode } from 'Frontend/generated/jar-resources/copilot.js';
|
||||
* import { _registerImporter } from 'Frontend/generated/jar-resources/copilot.js';
|
||||
*
|
||||
* function acmeCardImporter(node: FigmaNode): ComponentDefinition | undefined {
|
||||
* if (node.properties.type === 'AcmeCard') {
|
||||
* return {
|
||||
* tag: 'AcmeCard',
|
||||
* props: {
|
||||
* cardTitle: node.properties.title,
|
||||
* cardText: node.properties.content,
|
||||
* },
|
||||
* children: [],
|
||||
* javaClass: 'my.project.components.AcmeCard',
|
||||
* reactImports: {
|
||||
* AcmeCard: 'Frontend/components/AcmeCard',
|
||||
* },
|
||||
* };
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* _registerImporter(acmeCardImporter);
|
||||
* ```
|
||||
* If you only want to support either Java or React, you can omit the `javaClass` or `reactImports` property respectively.
|
||||
*
|
||||
* The above content should be placed in a file that is imported only in development mode, for example in `src/main/frontend/figma-importer.ts`.
|
||||
* In `index.tsx` you can then place
|
||||
* ```typescript
|
||||
* // @ts-ignore
|
||||
* if (import.meta.env.DEV) {
|
||||
* import('./figma-importer');
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Registered importers will be used before the built in importers, so you can override the built-in importers if needed.
|
||||
*
|
||||
* This method is experimental and may change in the future.
|
||||
*
|
||||
* @param importer the importer to register
|
||||
*/
|
||||
export declare function _registerImporter(importer: Importer): void;
|
||||
export declare function _registerInternalImporter(importer: Importer): void;
|
||||
export declare function _getImporters(): Importer[];
|
||||
export declare function _getIcon(node: FigmaNode, enablerKey: string, iconKey: string, slot?: string | undefined): ComponentDefinition | undefined;
|
||||
export declare function renderNodesAs(htmlTag: string, nodes: Array<FigmaNode | undefined>, metadata: ImportMetadata): ComponentDefinition[];
|
||||
export declare function renderNodeAs(htmlTag: string, node: FigmaNode, metadata: ImportMetadata, customProperties?: Record<string, string>): ComponentDefinition | undefined;
|
||||
export declare function renderNodes(childNodes: FigmaNode[], metadata: ImportMetadata): ComponentDefinition[];
|
||||
export declare function renderNode(node: FigmaNode, metadata: ImportMetadata, customProperties?: Record<string, string>): ComponentDefinition | undefined;
|
||||
export declare function findChild(node: FigmaNode, matcher: (node: FigmaNode) => boolean): FigmaNode | undefined;
|
||||
export declare function findFirstChild(node: FigmaNode, name: string): FigmaNode | undefined;
|
||||
4025
src/main/frontend/generated/jar-resources/copilot/icons-DVw-r69H.js
Normal file
4025
src/main/frontend/generated/jar-resources/copilot/icons-DVw-r69H.js
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,48 @@
|
||||
import { P as c } from "./copilot-CP3-W7yE.js";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
const d = (e, a, t) => (t.configurable = !0, t.enumerable = !0, Reflect.decorate && typeof a != "object" && Object.defineProperty(e, a, t), t);
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
function h(e, a) {
|
||||
return (t, o, v) => {
|
||||
const i = (l) => l.renderRoot?.querySelector(e) ?? null;
|
||||
return d(t, o, { get() {
|
||||
return i(this);
|
||||
} });
|
||||
};
|
||||
}
|
||||
function u(e) {
|
||||
e.querySelectorAll(
|
||||
"vaadin-context-menu, vaadin-menu-bar, vaadin-menu-bar-submenu, vaadin-select, vaadin-combo-box, vaadin-tooltip, vaadin-dialog, vaadin-multi-select-combo-box, vaadin-popover"
|
||||
).forEach((a) => {
|
||||
a?.$?.comboBox && (a = a.$.comboBox);
|
||||
let t = a.shadowRoot?.querySelector(
|
||||
`${a.localName}-overlay, ${a.localName}-submenu, vaadin-menu-bar-overlay`
|
||||
);
|
||||
t?.localName === "vaadin-menu-bar-submenu" && (t = t.shadowRoot.querySelector("vaadin-menu-bar-overlay")), t ? t._attachOverlay = n.bind(t) : a.$?.overlay && (a.$.overlay._attachOverlay = n.bind(a.$.overlay));
|
||||
});
|
||||
}
|
||||
function r() {
|
||||
return document.querySelector(`${c}main`).shadowRoot;
|
||||
}
|
||||
const m = () => Array.from(r().children).filter((a) => a._hasOverlayStackMixin && !a.hasAttribute("closing")).sort((a, t) => a.__zIndex - t.__zIndex || 0), s = (e) => e === m().pop();
|
||||
function n() {
|
||||
const e = this;
|
||||
e._placeholder = document.createComment("vaadin-overlay-placeholder"), e.parentNode.insertBefore(e._placeholder, e), r().appendChild(e), e.hasOwnProperty("_last") || Object.defineProperty(e, "_last", {
|
||||
// Only returns odd die sides
|
||||
get() {
|
||||
return s(this);
|
||||
}
|
||||
}), e.bringToFront(), requestAnimationFrame(() => u(e));
|
||||
}
|
||||
export {
|
||||
h as e,
|
||||
u as m
|
||||
};
|
||||
76
src/main/frontend/generated/jar-resources/copilot/shared/copilot-plugin-support.d.ts
vendored
Normal file
76
src/main/frontend/generated/jar-resources/copilot/shared/copilot-plugin-support.d.ts
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import { IObservableValue } from 'mobx';
|
||||
import { TemplateResult } from 'lit';
|
||||
/**
|
||||
* Plugin API for the dev tools window.
|
||||
*/
|
||||
export interface CopilotInterface {
|
||||
send(command: string, data: any): void;
|
||||
addPanel(panel: PanelConfiguration): void;
|
||||
}
|
||||
export interface MessageHandler {
|
||||
handleMessage(message: ServerMessage): boolean;
|
||||
}
|
||||
export interface ServerMessage {
|
||||
/**
|
||||
* The command
|
||||
*/
|
||||
command: string;
|
||||
/**
|
||||
* The data for the command
|
||||
*/
|
||||
data: any;
|
||||
}
|
||||
export type Framework = 'flow' | 'hilla-lit' | 'hilla-react';
|
||||
export interface CopilotPlugin {
|
||||
/**
|
||||
* Called once to initialize the plugin.
|
||||
*
|
||||
* @param copilotInterface provides methods to interact with the dev tools
|
||||
*/
|
||||
init(copilotInterface: CopilotInterface): void;
|
||||
}
|
||||
export declare enum MessageType {
|
||||
INFORMATION = "information",
|
||||
WARNING = "warning",
|
||||
ERROR = "error"
|
||||
}
|
||||
export interface Message {
|
||||
id: number;
|
||||
type: MessageType;
|
||||
message: string;
|
||||
timestamp: Date;
|
||||
details?: IObservableValue<TemplateResult> | string;
|
||||
link?: string;
|
||||
persistentId?: string;
|
||||
dontShowAgain: boolean;
|
||||
deleted: boolean;
|
||||
}
|
||||
export interface PanelConfiguration {
|
||||
header: string;
|
||||
expanded: boolean;
|
||||
expandable?: boolean;
|
||||
panel?: 'bottom' | 'left' | 'right';
|
||||
panelOrder: number;
|
||||
tag: string;
|
||||
actionsTag?: string;
|
||||
floating: boolean;
|
||||
height?: number;
|
||||
width?: number;
|
||||
floatingPosition?: FloatingPosition;
|
||||
showWhileDragging?: boolean;
|
||||
helpUrl?: string;
|
||||
/**
|
||||
* These panels can be visible regardless of copilot activation status
|
||||
*/
|
||||
individual?: boolean;
|
||||
/**
|
||||
* A panel is rendered the first time when it is expanded unless eager is set to true, which causes it be always be rendered
|
||||
*/
|
||||
eager?: boolean;
|
||||
}
|
||||
export interface FloatingPosition {
|
||||
top?: number;
|
||||
left?: number;
|
||||
right?: number;
|
||||
bottom?: number;
|
||||
}
|
||||
41
src/main/frontend/generated/jar-resources/copilot/shared/flow-utils.d.ts
vendored
Normal file
41
src/main/frontend/generated/jar-resources/copilot/shared/flow-utils.d.ts
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
import { FiberNode, Source } from 'react-devtools-inline';
|
||||
import { CopilotTreeNode } from './copilot-tree';
|
||||
import { JavaSource } from '../show-in-ide';
|
||||
export type FlowComponentReference = {
|
||||
nodeId: number;
|
||||
uiId: number;
|
||||
};
|
||||
export type FlowComponentInfo = FlowComponentReference & {
|
||||
element: HTMLElement;
|
||||
javaClass?: string;
|
||||
hiddenByServer: boolean;
|
||||
styles: Record<string, string>;
|
||||
};
|
||||
export type ComponentDefinitionProperties = Record<string, any[] | Record<string, any> | boolean | number | string | null>;
|
||||
export type ComponentDefinition = {
|
||||
tag?: string;
|
||||
className?: string;
|
||||
props: ComponentDefinitionProperties;
|
||||
children: Array<ComponentDefinition | string>;
|
||||
reactImports?: Record<string, string>;
|
||||
javaClass?: string;
|
||||
metadata?: any;
|
||||
};
|
||||
export declare function isFlowComponentInfo(info: FlowComponentInfo | JavaSource | Source | undefined): info is FlowComponentInfo;
|
||||
export declare function isFlowComponent(element: HTMLElement): boolean;
|
||||
export declare function getJavaClassName(component: FlowComponentInfo): string | undefined;
|
||||
export declare function getFlowComponent(element: HTMLElement): FlowComponentInfo | undefined;
|
||||
export declare const fetchComponentDefinition: (flowComponent: FlowComponentInfo) => Promise<ComponentDefinition>;
|
||||
export declare function getUIId(): string | undefined;
|
||||
export declare function getFlowComponentId(flowComponent: FlowComponentInfo): FlowComponentReference;
|
||||
export declare function isServerRouteContainer(fiber?: FiberNode): boolean;
|
||||
export declare const isEditableComponentText: (node: CopilotTreeNode | undefined, propertyToCheck: string) => Promise<{
|
||||
canBeEdited: boolean;
|
||||
isTranslation: boolean;
|
||||
}> | {
|
||||
canBeEdited: boolean;
|
||||
isTranslation: boolean;
|
||||
};
|
||||
export declare function isServerRouteContainerElement(element: HTMLElement): boolean;
|
||||
export declare function getSimpleName(className: string): string;
|
||||
export declare function getPackageName(className: string): string;
|
||||
@@ -0,0 +1,45 @@
|
||||
import { ap as u, aq as p } from "./copilot-CP3-W7yE.js";
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
const l = { attribute: !0, type: String, converter: p, reflect: !1, hasChanged: u }, d = (t = l, o, e) => {
|
||||
const { kind: s, metadata: i } = e;
|
||||
let r = globalThis.litPropertyMetadata.get(i);
|
||||
if (r === void 0 && globalThis.litPropertyMetadata.set(i, r = /* @__PURE__ */ new Map()), s === "setter" && ((t = Object.create(t)).wrapped = !0), r.set(e.name, t), s === "accessor") {
|
||||
const { name: a } = e;
|
||||
return { set(n) {
|
||||
const c = o.get.call(this);
|
||||
o.set.call(this, n), this.requestUpdate(a, c, t);
|
||||
}, init(n) {
|
||||
return n !== void 0 && this.C(a, void 0, t, n), n;
|
||||
} };
|
||||
}
|
||||
if (s === "setter") {
|
||||
const { name: a } = e;
|
||||
return function(n) {
|
||||
const c = this[a];
|
||||
o.call(this, n), this.requestUpdate(a, c, t);
|
||||
};
|
||||
}
|
||||
throw Error("Unsupported decorator location: " + s);
|
||||
};
|
||||
function h(t) {
|
||||
return (o, e) => typeof e == "object" ? d(t, o, e) : ((s, i, r) => {
|
||||
const a = i.hasOwnProperty(r);
|
||||
return i.constructor.createProperty(r, s), a ? Object.getOwnPropertyDescriptor(i, r) : void 0;
|
||||
})(t, o, e);
|
||||
}
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
function b(t) {
|
||||
return h({ ...t, state: !0, attribute: !1 });
|
||||
}
|
||||
export {
|
||||
h as n,
|
||||
b as r
|
||||
};
|
||||
179
src/main/frontend/generated/jar-resources/datepickerConnector.js
Normal file
179
src/main/frontend/generated/jar-resources/datepickerConnector.js
Normal file
@@ -0,0 +1,179 @@
|
||||
import dateFnsFormat from 'date-fns/format';
|
||||
import dateFnsParse from 'date-fns/parse';
|
||||
import dateFnsIsValid from 'date-fns/isValid';
|
||||
import { extractDateParts, parseDate as _parseDate } from '@vaadin/date-picker/src/vaadin-date-picker-helper.js';
|
||||
|
||||
window.Vaadin.Flow.datepickerConnector = {};
|
||||
window.Vaadin.Flow.datepickerConnector.initLazy = (datepicker) => {
|
||||
// Check whether the connector was already initialized for the datepicker
|
||||
if (datepicker.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
datepicker.$connector = {};
|
||||
|
||||
const createLocaleBasedDateFormat = function (locale) {
|
||||
try {
|
||||
// Check whether the locale is supported or not
|
||||
new Date().toLocaleDateString(locale);
|
||||
} catch (e) {
|
||||
console.warn('The locale is not supported, using default format setting (ISO 8601).');
|
||||
return 'yyyy-MM-dd';
|
||||
}
|
||||
|
||||
// format test date and convert to date-fns pattern
|
||||
const testDate = new Date(Date.UTC(1234, 4, 6));
|
||||
let pattern = testDate.toLocaleDateString(locale, { timeZone: 'UTC' });
|
||||
pattern = pattern
|
||||
// escape date-fns pattern letters by enclosing them in single quotes
|
||||
.replace(/([a-zA-Z]+)/g, "'$1'")
|
||||
// insert date placeholder
|
||||
.replace('06', 'dd')
|
||||
.replace('6', 'd')
|
||||
// insert month placeholder
|
||||
.replace('05', 'MM')
|
||||
.replace('5', 'M')
|
||||
// insert year placeholder
|
||||
.replace('1234', 'yyyy');
|
||||
const isValidPattern = pattern.includes('d') && pattern.includes('M') && pattern.includes('y');
|
||||
if (!isValidPattern) {
|
||||
console.warn('The locale is not supported, using default format setting (ISO 8601).');
|
||||
return 'yyyy-MM-dd';
|
||||
}
|
||||
|
||||
return pattern;
|
||||
};
|
||||
|
||||
function createFormatterAndParser(formats) {
|
||||
if (!formats || formats.length === 0) {
|
||||
throw new Error('Array of custom date formats is null or empty');
|
||||
}
|
||||
|
||||
function getShortYearFormat(format) {
|
||||
if (format.includes('yyyy') && !format.includes('yyyyy')) {
|
||||
return format.replace('yyyy', 'yy');
|
||||
}
|
||||
if (format.includes('YYYY') && !format.includes('YYYYY')) {
|
||||
return format.replace('YYYY', 'YY');
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isFormatWithYear(format) {
|
||||
return format.includes('y') || format.includes('Y');
|
||||
}
|
||||
|
||||
function isShortYearFormat(format) {
|
||||
// Format is long if it includes a four-digit year.
|
||||
return !format.includes('yyyy') && !format.includes('YYYY');
|
||||
}
|
||||
|
||||
function getExtendedFormats(formats) {
|
||||
return formats.reduce((acc, format) => {
|
||||
// We first try to match the date with the shorter version,
|
||||
// as short years are supported with the long date format.
|
||||
if (isFormatWithYear(format) && !isShortYearFormat(format)) {
|
||||
acc.push(getShortYearFormat(format));
|
||||
}
|
||||
acc.push(format);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function correctFullYear(date) {
|
||||
// The last parsed date check handles the case where a four-digit year is parsed, then formatted
|
||||
// as a two-digit year, and then parsed again. In this case we want to keep the century of the
|
||||
// originally parsed year, instead of using the century of the reference date.
|
||||
|
||||
// Do not apply any correction if the previous parse attempt was failed.
|
||||
if (datepicker.$connector._lastParseStatus === 'error') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update century if the last parsed date is the same except the century.
|
||||
if (datepicker.$connector._lastParseStatus === 'successful') {
|
||||
if (
|
||||
datepicker.$connector._lastParsedDate.day === date.getDate() &&
|
||||
datepicker.$connector._lastParsedDate.month === date.getMonth() &&
|
||||
datepicker.$connector._lastParsedDate.year % 100 === date.getFullYear() % 100
|
||||
) {
|
||||
date.setFullYear(datepicker.$connector._lastParsedDate.year);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Update century if this is the first parse after overlay open.
|
||||
const currentValue = _parseDate(datepicker.value);
|
||||
if (
|
||||
dateFnsIsValid(currentValue) &&
|
||||
currentValue.getDate() === date.getDate() &&
|
||||
currentValue.getMonth() === date.getMonth() &&
|
||||
currentValue.getFullYear() % 100 === date.getFullYear() % 100
|
||||
) {
|
||||
date.setFullYear(currentValue.getFullYear());
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(dateParts) {
|
||||
const format = formats[0];
|
||||
const date = _parseDate(`${dateParts.year}-${dateParts.month + 1}-${dateParts.day}`);
|
||||
|
||||
return dateFnsFormat(date, format);
|
||||
}
|
||||
|
||||
function doParseDate(dateString, format, referenceDate) {
|
||||
// When format does not contain a year, then current year should be used.
|
||||
const refDate = isFormatWithYear(format) ? referenceDate : new Date();
|
||||
const date = dateFnsParse(dateString, format, refDate);
|
||||
if (dateFnsIsValid(date)) {
|
||||
if (isFormatWithYear(format) && isShortYearFormat(format)) {
|
||||
correctFullYear(date);
|
||||
}
|
||||
return {
|
||||
day: date.getDate(),
|
||||
month: date.getMonth(),
|
||||
year: date.getFullYear()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function parseDate(dateString) {
|
||||
const referenceDate = _getReferenceDate();
|
||||
for (let format of getExtendedFormats(formats)) {
|
||||
const parsedDate = doParseDate(dateString, format, referenceDate);
|
||||
if (parsedDate) {
|
||||
datepicker.$connector._lastParseStatus = 'successful';
|
||||
datepicker.$connector._lastParsedDate = parsedDate;
|
||||
return parsedDate;
|
||||
}
|
||||
}
|
||||
datepicker.$connector._lastParseStatus = 'error';
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
formatDate: formatDate,
|
||||
parseDate: parseDate
|
||||
};
|
||||
}
|
||||
|
||||
function _getReferenceDate() {
|
||||
const { referenceDate } = datepicker.i18n;
|
||||
return referenceDate ? new Date(referenceDate.year, referenceDate.month, referenceDate.day) : new Date();
|
||||
}
|
||||
|
||||
datepicker.$connector.updateI18n = (locale, i18n) => {
|
||||
// Either use custom formats specified in I18N, or create format from locale
|
||||
const hasCustomFormats = i18n && i18n.dateFormats && i18n.dateFormats.length > 0;
|
||||
if (i18n && i18n.referenceDate) {
|
||||
i18n.referenceDate = extractDateParts(new Date(i18n.referenceDate));
|
||||
}
|
||||
const usedFormats = hasCustomFormats ? i18n.dateFormats : [createLocaleBasedDateFormat(locale)];
|
||||
const formatterAndParser = createFormatterAndParser(usedFormats);
|
||||
|
||||
// Merge current web component I18N settings with new I18N settings and the formatting and parsing functions
|
||||
datepicker.i18n = Object.assign({}, datepicker.i18n, i18n, formatterAndParser);
|
||||
};
|
||||
|
||||
datepicker.addEventListener('opened-changed', () => (datepicker.$connector._lastParseStatus = undefined));
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
document.addEventListener('click', (event) => {
|
||||
const target = event.composedPath().find((node) => node.hasAttribute && node.hasAttribute('disableonclick'));
|
||||
if (target) {
|
||||
target.disabled = true;
|
||||
}
|
||||
});
|
||||
130
src/main/frontend/generated/jar-resources/dndConnector.js
Normal file
130
src/main/frontend/generated/jar-resources/dndConnector.js
Normal file
@@ -0,0 +1,130 @@
|
||||
window.Vaadin = window.Vaadin || {};
|
||||
window.Vaadin.Flow = window.Vaadin.Flow || {};
|
||||
window.Vaadin.Flow.dndConnector = {
|
||||
__ondragenterListener: function (event) {
|
||||
// TODO filter by data type
|
||||
// TODO prevent dropping on itself (by default)
|
||||
const effect = event.currentTarget['__dropEffect'];
|
||||
if (!event.currentTarget.hasAttribute('disabled')) {
|
||||
if (effect) {
|
||||
event.dataTransfer.dropEffect = effect;
|
||||
}
|
||||
|
||||
if (effect !== 'none') {
|
||||
/* #7108: if drag moves on top of drop target's children, first another ondragenter event
|
||||
* is fired and then a ondragleave event. This happens again once the drag
|
||||
* moves on top of another children, or back on top of the drop target element.
|
||||
* Thus need to "cancel" the following ondragleave, to not remove class name.
|
||||
* Drop event will happen even when dropped to a child element. */
|
||||
if (event.currentTarget.classList.contains('v-drag-over-target')) {
|
||||
event.currentTarget['__skip-leave'] = true;
|
||||
} else {
|
||||
event.currentTarget.classList.add('v-drag-over-target');
|
||||
}
|
||||
// enables browser specific pseudo classes (at least FF)
|
||||
event.preventDefault();
|
||||
event.stopPropagation(); // don't let parents know
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
__ondragoverListener: function (event) {
|
||||
// TODO filter by data type
|
||||
// TODO filter by effectAllowed != dropEffect due to Safari & IE11 ?
|
||||
if (!event.currentTarget.hasAttribute('disabled')) {
|
||||
const effect = event.currentTarget['__dropEffect'];
|
||||
if (effect) {
|
||||
event.dataTransfer.dropEffect = effect;
|
||||
}
|
||||
// allows the drop && don't let parents know
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
__ondragleaveListener: function (event) {
|
||||
if (event.currentTarget['__skip-leave']) {
|
||||
event.currentTarget['__skip-leave'] = false;
|
||||
} else {
|
||||
event.currentTarget.classList.remove('v-drag-over-target');
|
||||
}
|
||||
// #7109 need to stop or any parent drop target might not get highlighted,
|
||||
// as ondragenter for it is fired before the child gets dragleave.
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
__ondropListener: function (event) {
|
||||
const effect = event.currentTarget['__dropEffect'];
|
||||
if (effect) {
|
||||
event.dataTransfer.dropEffect = effect;
|
||||
}
|
||||
event.currentTarget.classList.remove('v-drag-over-target');
|
||||
// prevent browser handling && don't let parents know
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
},
|
||||
|
||||
updateDropTarget: function (element) {
|
||||
if (element['__active']) {
|
||||
element.addEventListener('dragenter', this.__ondragenterListener, false);
|
||||
element.addEventListener('dragover', this.__ondragoverListener, false);
|
||||
element.addEventListener('dragleave', this.__ondragleaveListener, false);
|
||||
element.addEventListener('drop', this.__ondropListener, false);
|
||||
} else {
|
||||
element.removeEventListener('dragenter', this.__ondragenterListener, false);
|
||||
element.removeEventListener('dragover', this.__ondragoverListener, false);
|
||||
element.removeEventListener('dragleave', this.__ondragleaveListener, false);
|
||||
element.removeEventListener('drop', this.__ondropListener, false);
|
||||
element.classList.remove('v-drag-over-target');
|
||||
}
|
||||
},
|
||||
|
||||
/** DRAG SOURCE METHODS: */
|
||||
|
||||
__dragstartListener: function (event) {
|
||||
event.stopPropagation();
|
||||
event.dataTransfer.setData('text/plain', '');
|
||||
if (event.currentTarget.hasAttribute('disabled')) {
|
||||
event.preventDefault();
|
||||
} else {
|
||||
if (event.currentTarget['__effectAllowed']) {
|
||||
event.dataTransfer.effectAllowed = event.currentTarget['__effectAllowed'];
|
||||
}
|
||||
event.currentTarget.classList.add('v-dragged');
|
||||
}
|
||||
if(event.currentTarget.__dragImage) {
|
||||
if(event.currentTarget.__dragImage.style.display === "none") {
|
||||
event.currentTarget.__dragImage.style.display = "block";
|
||||
event.currentTarget.classList.add('shown');
|
||||
}
|
||||
event.dataTransfer.setDragImage(
|
||||
event.currentTarget.__dragImage,
|
||||
event.currentTarget.__dragImageOffsetX,
|
||||
event.currentTarget.__dragImageOffsetY);
|
||||
}
|
||||
},
|
||||
|
||||
__dragendListener: function (event) {
|
||||
event.currentTarget.classList.remove('v-dragged');
|
||||
if(event.currentTarget.classList.contains('shown')) {
|
||||
event.currentTarget.classList.remove('shown');
|
||||
event.currentTarget.__dragImage.style.display = "none";
|
||||
}
|
||||
},
|
||||
|
||||
updateDragSource: function (element) {
|
||||
if (element['draggable']) {
|
||||
element.addEventListener('dragstart', this.__dragstartListener, false);
|
||||
element.addEventListener('dragend', this.__dragendListener, false);
|
||||
} else {
|
||||
element.removeEventListener('dragstart', this.__dragstartListener, false);
|
||||
element.removeEventListener('dragend', this.__dragendListener, false);
|
||||
}
|
||||
},
|
||||
|
||||
setDragImage: function (dragImage, offsetX, offsetY, dragSource) {
|
||||
dragSource.__dragImage = dragImage;
|
||||
dragSource.__dragImageOffsetX = offsetX;
|
||||
dragSource.__dragImageOffsetY = offsetY;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
import { noChange } from 'lit';
|
||||
import { directive, PartType } from 'lit/directive.js';
|
||||
import { AsyncDirective } from 'lit/async-directive.js';
|
||||
|
||||
class FlowComponentDirective extends AsyncDirective {
|
||||
constructor(partInfo) {
|
||||
super(partInfo);
|
||||
if (partInfo.type !== PartType.CHILD) {
|
||||
throw new Error(`${this.constructor.directiveName}() can only be used in child bindings`);
|
||||
}
|
||||
}
|
||||
|
||||
update(part, [appid, nodeid]) {
|
||||
this.updateContent(part, appid, nodeid);
|
||||
return noChange;
|
||||
}
|
||||
|
||||
updateContent(part, appid, nodeid) {
|
||||
const { parentNode, startNode } = part;
|
||||
this.__parentNode = parentNode;
|
||||
|
||||
const hasNewNodeId = nodeid !== undefined && nodeid !== null;
|
||||
const newNode = hasNewNodeId ? this.getNewNode(appid, nodeid) : null;
|
||||
const oldNode = this.getOldNode(part);
|
||||
|
||||
clearTimeout(this.__parentNode.__nodeRetryTimeout);
|
||||
|
||||
if (hasNewNodeId && !newNode) {
|
||||
// If the node is not found, try again later.
|
||||
this.__parentNode.__nodeRetryTimeout = setTimeout(() => this.updateContent(part, appid, nodeid));
|
||||
} else if (oldNode === newNode) {
|
||||
return;
|
||||
} else if (oldNode && newNode) {
|
||||
parentNode.replaceChild(newNode, oldNode);
|
||||
} else if (oldNode) {
|
||||
parentNode.removeChild(oldNode);
|
||||
} else if (newNode) {
|
||||
startNode.after(newNode);
|
||||
}
|
||||
}
|
||||
|
||||
getNewNode(appid, nodeid) {
|
||||
return window.Vaadin.Flow.clients[appid].getByNodeId(nodeid);
|
||||
}
|
||||
|
||||
getOldNode(part) {
|
||||
const { startNode, endNode } = part;
|
||||
if (startNode.nextSibling === endNode) {
|
||||
return;
|
||||
}
|
||||
return startNode.nextSibling;
|
||||
}
|
||||
|
||||
disconnected() {
|
||||
clearTimeout(this.__parentNode.__nodeRetryTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the given flow component node.
|
||||
*
|
||||
* WARNING: This directive is not intended for public use.
|
||||
*
|
||||
* @param {string} appid
|
||||
* @param {number} nodeid
|
||||
* @private
|
||||
*/
|
||||
export const flowComponentDirective = directive(FlowComponentDirective);
|
||||
@@ -0,0 +1,198 @@
|
||||
import '@polymer/polymer/lib/elements/dom-if.js';
|
||||
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
||||
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
|
||||
import { idlePeriod } from '@polymer/polymer/lib/utils/async.js';
|
||||
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||
import { flowComponentDirective } from './flow-component-directive.js';
|
||||
import { render, html as litHtml } from 'lit';
|
||||
|
||||
/**
|
||||
* Returns the requested node in a form suitable for Lit template interpolation.
|
||||
* @param {string} appid
|
||||
* @param {number} nodeid
|
||||
* @returns {any} a Lit directive
|
||||
*/
|
||||
function getNode(appid, nodeid) {
|
||||
return flowComponentDirective(appid, nodeid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nodes defined by the given node ids as the child nodes of the
|
||||
* given root element.
|
||||
* @param {string} appid
|
||||
* @param {number[]} nodeIds
|
||||
* @param {Element} root
|
||||
*/
|
||||
function setChildNodes(appid, nodeIds, root) {
|
||||
render(litHtml`${nodeIds.map((id) => flowComponentDirective(appid, id))}`, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleElementBindingStrategy::addChildren uses insertBefore to add child
|
||||
* elements to the container. When the children are manually placed under
|
||||
* another element, the call to insertBefore can occasionally fail due to
|
||||
* an invalid reference node.
|
||||
*
|
||||
* This is a temporary workaround which patches the container's native API
|
||||
* to not fail when called with invalid arguments.
|
||||
*/
|
||||
function patchVirtualContainer(container) {
|
||||
const originalInsertBefore = container.insertBefore;
|
||||
|
||||
container.insertBefore = function (newNode, referenceNode) {
|
||||
if (referenceNode && referenceNode.parentNode === this) {
|
||||
return originalInsertBefore.call(this, newNode, referenceNode);
|
||||
} else {
|
||||
return originalInsertBefore.call(this, newNode, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
window.Vaadin ||= {};
|
||||
window.Vaadin.FlowComponentHost ||= { patchVirtualContainer, getNode, setChildNodes };
|
||||
|
||||
class FlowComponentRenderer extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
animation: 1ms flow-component-renderer-appear;
|
||||
}
|
||||
|
||||
@keyframes flow-component-renderer-appear {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<slot></slot>
|
||||
`;
|
||||
}
|
||||
|
||||
static get is() {
|
||||
return 'flow-component-renderer';
|
||||
}
|
||||
static get properties() {
|
||||
return {
|
||||
nodeid: Number,
|
||||
appid: String
|
||||
};
|
||||
}
|
||||
static get observers() {
|
||||
return ['_attachRenderedComponentIfAble(appid, nodeid)'];
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
this.addEventListener('click', function (event) {
|
||||
if (this.firstChild && typeof this.firstChild.click === 'function' && event.target === this) {
|
||||
event.stopPropagation();
|
||||
this.firstChild.click();
|
||||
}
|
||||
});
|
||||
this.addEventListener('animationend', this._onAnimationEnd);
|
||||
}
|
||||
|
||||
_asyncAttachRenderedComponentIfAble() {
|
||||
this._debouncer = Debouncer.debounce(this._debouncer, idlePeriod, () => this._attachRenderedComponentIfAble());
|
||||
}
|
||||
|
||||
_attachRenderedComponentIfAble() {
|
||||
if (this.appid == null) {
|
||||
return;
|
||||
}
|
||||
if (this.nodeid == null) {
|
||||
if (this.firstChild) {
|
||||
this.removeChild(this.firstChild);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const renderedComponent = this._getRenderedComponent();
|
||||
if (this.firstChild) {
|
||||
if (!renderedComponent) {
|
||||
this._asyncAttachRenderedComponentIfAble();
|
||||
} else if (this.firstChild !== renderedComponent) {
|
||||
this.replaceChild(renderedComponent, this.firstChild);
|
||||
this._defineFocusTarget();
|
||||
this.onComponentRendered();
|
||||
} else {
|
||||
this._defineFocusTarget();
|
||||
this.onComponentRendered();
|
||||
}
|
||||
} else {
|
||||
if (renderedComponent) {
|
||||
this.appendChild(renderedComponent);
|
||||
this._defineFocusTarget();
|
||||
this.onComponentRendered();
|
||||
} else {
|
||||
this._asyncAttachRenderedComponentIfAble();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_getRenderedComponent() {
|
||||
try {
|
||||
return window.Vaadin.Flow.clients[this.appid].getByNodeId(this.nodeid);
|
||||
} catch (error) {
|
||||
console.error('Could not get node %s from app %s', this.nodeid, this.appid);
|
||||
console.error(error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
onComponentRendered() {
|
||||
// subclasses can override this method to execute custom logic on resize
|
||||
}
|
||||
|
||||
/* Setting the `focus-target` attribute to the first focusable descendant
|
||||
starting from the firstChild necessary for the focus to be delegated
|
||||
within the flow-component-renderer when used inside a vaadin-grid cell */
|
||||
_defineFocusTarget() {
|
||||
var focusable = this._getFirstFocusableDescendant(this.firstChild);
|
||||
if (focusable !== null) {
|
||||
focusable.setAttribute('focus-target', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
_getFirstFocusableDescendant(node) {
|
||||
if (this._isFocusable(node)) {
|
||||
return node;
|
||||
}
|
||||
if (node.hasAttribute && (node.hasAttribute('disabled') || node.hasAttribute('hidden'))) {
|
||||
return null;
|
||||
}
|
||||
if (!node.children) {
|
||||
return null;
|
||||
}
|
||||
for (var i = 0; i < node.children.length; i++) {
|
||||
var focusable = this._getFirstFocusableDescendant(node.children[i]);
|
||||
if (focusable !== null) {
|
||||
return focusable;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_isFocusable(node) {
|
||||
if (
|
||||
node.hasAttribute &&
|
||||
typeof node.hasAttribute === 'function' &&
|
||||
(node.hasAttribute('disabled') || node.hasAttribute('hidden'))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return node.tabIndex === 0;
|
||||
}
|
||||
|
||||
_onAnimationEnd(e) {
|
||||
// ShadyCSS applies scoping suffixes to animation names
|
||||
// To ensure that child is attached once element is unhidden
|
||||
// for when it was filtered out from, eg, ComboBox
|
||||
// https://github.com/vaadin/vaadin-flow-components/issues/437
|
||||
if (e.animationName.indexOf('flow-component-renderer-appear') === 0) {
|
||||
this._attachRenderedComponentIfAble();
|
||||
}
|
||||
}
|
||||
}
|
||||
window.customElements.define(FlowComponentRenderer.is, FlowComponentRenderer);
|
||||
1174
src/main/frontend/generated/jar-resources/gridConnector.ts
Normal file
1174
src/main/frontend/generated/jar-resources/gridConnector.ts
Normal file
File diff suppressed because it is too large
Load Diff
2
src/main/frontend/generated/jar-resources/index.d.ts
vendored
Normal file
2
src/main/frontend/generated/jar-resources/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './copilot'
|
||||
export {}
|
||||
2
src/main/frontend/generated/jar-resources/index.js
Normal file
2
src/main/frontend/generated/jar-resources/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './Flow';
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
src/main/frontend/generated/jar-resources/index.js.map
Normal file
1
src/main/frontend/generated/jar-resources/index.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/main/frontend/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC","sourcesContent":["export * from './Flow';\n"]}
|
||||
112
src/main/frontend/generated/jar-resources/lit-renderer.ts
Normal file
112
src/main/frontend/generated/jar-resources/lit-renderer.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
/* eslint-disable max-params */
|
||||
import { html, render } from 'lit';
|
||||
import { live } from 'lit/directives/live.js';
|
||||
|
||||
type RenderRoot = HTMLElement & { __litRenderer?: Renderer; _$litPart$?: any };
|
||||
|
||||
type ItemModel = { item: any; index: number };
|
||||
|
||||
type Renderer = ((root: RenderRoot, rendererOwner: HTMLElement, model: ItemModel) => void) & { __rendererId?: string };
|
||||
|
||||
type Component = HTMLElement & { [key: string]: Renderer | undefined };
|
||||
|
||||
const _window = window as any;
|
||||
_window.Vaadin = _window.Vaadin || {};
|
||||
|
||||
/**
|
||||
* Assigns the component a renderer function which uses Lit to render
|
||||
* the given template expression inside the render root element.
|
||||
*
|
||||
* @param component The host component to which the renderer runction is to be set
|
||||
* @param rendererName The name of the renderer function
|
||||
* @param templateExpression The content of the template literal passed to Lit for rendering.
|
||||
* @param returnChannel A channel to the server.
|
||||
* Calling it will end up invoking a handler in the server-side LitRenderer.
|
||||
* @param clientCallables A list of function names that can be called from within the template literal.
|
||||
* @param propertyNamespace LitRenderer-specific namespace for properties.
|
||||
* Needed to avoid property name collisions between renderers.
|
||||
*/
|
||||
_window.Vaadin.setLitRenderer = (
|
||||
component: Component,
|
||||
rendererName: string,
|
||||
templateExpression: string,
|
||||
returnChannel: (name: string, itemKey: string, args: any[]) => void,
|
||||
clientCallables: string[],
|
||||
propertyNamespace: string,
|
||||
appId: string
|
||||
) => {
|
||||
const callablesCreator = (itemKey: string) => {
|
||||
return clientCallables.map((clientCallable) => (...args: any[]) => {
|
||||
if (itemKey !== undefined) {
|
||||
returnChannel(clientCallable, itemKey, args[0] instanceof Event ? [] : [...args]);
|
||||
}
|
||||
});
|
||||
};
|
||||
const fnArgs = [
|
||||
'html',
|
||||
'root',
|
||||
'live',
|
||||
'appId',
|
||||
'itemKey',
|
||||
'model',
|
||||
'item',
|
||||
'index',
|
||||
...clientCallables,
|
||||
`return html\`${templateExpression}\``
|
||||
];
|
||||
const htmlGenerator = new Function(...fnArgs);
|
||||
const renderFunction = (root: RenderRoot, model: ItemModel, itemKey: string) => {
|
||||
const { item, index } = model;
|
||||
render(htmlGenerator(html, root, live, appId, itemKey, model, item, index, ...callablesCreator(itemKey)), root);
|
||||
};
|
||||
|
||||
const renderer: Renderer = (root, _, model) => {
|
||||
const { item } = model;
|
||||
// Clean up the root element of any existing content
|
||||
// (and Lit's _$litPart$ property) from other renderers
|
||||
// TODO: Remove once https://github.com/vaadin/web-components/issues/2235 is done
|
||||
if (root.__litRenderer !== renderer) {
|
||||
root.innerHTML = '';
|
||||
delete root._$litPart$;
|
||||
root.__litRenderer = renderer;
|
||||
}
|
||||
|
||||
// Map a new item that only includes the properties defined by
|
||||
// this specific LitRenderer instance. The renderer instance specific
|
||||
// "propertyNamespace" prefix is stripped from the property name at this point:
|
||||
//
|
||||
// item: { key: "2", lr_3769df5394a74ef3_lastName: "Tyler"}
|
||||
// ->
|
||||
// mappedItem: { lastName: "Tyler" }
|
||||
const mappedItem: { [key: string]: any } = {};
|
||||
for (const key in item) {
|
||||
if (key.startsWith(propertyNamespace)) {
|
||||
mappedItem[key.replace(propertyNamespace, '')] = item[key];
|
||||
}
|
||||
}
|
||||
|
||||
renderFunction(root, { ...model, item: mappedItem }, item.key);
|
||||
};
|
||||
|
||||
renderer.__rendererId = propertyNamespace;
|
||||
component[rendererName] = renderer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the renderer function with the given name from the component
|
||||
* if the propertyNamespace matches the renderer's id.
|
||||
*
|
||||
* @param component The host component whose renderer function is to be removed
|
||||
* @param rendererName The name of the renderer function
|
||||
* @param rendererId The rendererId of the function to be removed
|
||||
*/
|
||||
_window.Vaadin.unsetLitRenderer = (component: Component, rendererName: string, rendererId: string) => {
|
||||
// The check for __rendererId property is necessary since the renderer function
|
||||
// may get overridden by another renderer, for example, by one coming from
|
||||
// vaadin-template-renderer. We don't want LitRenderer registration cleanup to
|
||||
// unintentionally remove the new renderer.
|
||||
if (component[rendererName]?.__rendererId === rendererId) {
|
||||
component[rendererName] = undefined;
|
||||
}
|
||||
};
|
||||
110
src/main/frontend/generated/jar-resources/menubarConnector.js
Normal file
110
src/main/frontend/generated/jar-resources/menubarConnector.js
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2000-2025 Vaadin Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
import './contextMenuConnector.js';
|
||||
|
||||
/**
|
||||
* Initializes the connector for a menu bar element.
|
||||
*
|
||||
* @param {HTMLElement} menubar
|
||||
* @param {string} appId
|
||||
*/
|
||||
function initLazy(menubar, appId) {
|
||||
if (menubar.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((records) => {
|
||||
const hasChangedAttributes = records.some((entry) => {
|
||||
const oldValue = entry.oldValue;
|
||||
const newValue = entry.target.getAttribute(entry.attributeName);
|
||||
return oldValue !== newValue;
|
||||
});
|
||||
|
||||
if (hasChangedAttributes) {
|
||||
menubar.$connector.generateItems();
|
||||
}
|
||||
});
|
||||
|
||||
menubar.$connector = {
|
||||
/**
|
||||
* Generates and assigns the items to the menu bar.
|
||||
*
|
||||
* When the method is called without providing a node id,
|
||||
* the previously generated items tree will be used.
|
||||
* That can be useful if you only want to sync the disabled and hidden properties of root items.
|
||||
*
|
||||
* @param {number | undefined} nodeId
|
||||
*/
|
||||
generateItems(nodeId) {
|
||||
if (!menubar.shadowRoot) {
|
||||
// workaround for https://github.com/vaadin/flow/issues/5722
|
||||
setTimeout(() => menubar.$connector.generateItems(nodeId));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!menubar._container) {
|
||||
// Menu-bar defers first buttons render to avoid re-layout
|
||||
// See https://github.com/vaadin/web-components/issues/7271
|
||||
queueMicrotask(() => menubar.$connector.generateItems(nodeId));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nodeId) {
|
||||
menubar.__generatedItems = window.Vaadin.Flow.contextMenuConnector.generateItemsTree(appId, nodeId);
|
||||
}
|
||||
|
||||
let items = menubar.__generatedItems || [];
|
||||
|
||||
items.forEach((item) => {
|
||||
// Propagate disabled state from items to parent buttons
|
||||
item.disabled = item.component.disabled;
|
||||
|
||||
// Saving item to component because `_item` can be reassigned to a new value
|
||||
// when the component goes to the overflow menu
|
||||
item.component._rootItem = item;
|
||||
});
|
||||
|
||||
// Observe for hidden and disabled attributes in case they are changed by Flow.
|
||||
// When a change occurs, the observer will re-generate items on top of the existing tree
|
||||
// to sync the new attribute values with the corresponding properties in the items array.
|
||||
items.forEach((item) => {
|
||||
observer.observe(item.component, {
|
||||
attributeFilter: ['hidden', 'disabled'],
|
||||
attributeOldValue: true
|
||||
});
|
||||
});
|
||||
|
||||
// Remove hidden items entirely from the array. Just hiding them
|
||||
// could cause the overflow button to be rendered without items.
|
||||
//
|
||||
// The items-prop needs to be set even when all items are visible
|
||||
// to update the disabled state and re-render buttons.
|
||||
items = items.filter((item) => !item.component.hidden);
|
||||
|
||||
menubar.items = items;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setClassName(component) {
|
||||
const item = component._rootItem || component._item;
|
||||
|
||||
if (item) {
|
||||
item.className = component.className;
|
||||
}
|
||||
}
|
||||
|
||||
window.Vaadin.Flow.menubarConnector = { initLazy, setClassName };
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2000-2025 Vaadin Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Maps the given items to a new array of items with formatted time.
|
||||
*/
|
||||
function formatItems(items, locale) {
|
||||
const formatter = new Intl.DateTimeFormat(locale, {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric'
|
||||
});
|
||||
|
||||
return items.map((item) =>
|
||||
item.time
|
||||
? Object.assign(item, {
|
||||
time: formatter.format(new Date(item.time))
|
||||
})
|
||||
: item
|
||||
);
|
||||
}
|
||||
|
||||
window.Vaadin.Flow.messageListConnector = {
|
||||
/**
|
||||
* Fully replaces the items in the list with the given items.
|
||||
*/
|
||||
setItems(list, items, locale) {
|
||||
list.items = formatItems(items, locale);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the text of the item at the given index to the given text.
|
||||
*/
|
||||
setItemText(list, text, index) {
|
||||
list.items[index].text = text;
|
||||
list.items = [...list.items];
|
||||
},
|
||||
|
||||
/**
|
||||
* Appends the given text to the text of the item at the given index.
|
||||
*/
|
||||
appendItemText(list, appendedText, index) {
|
||||
const currentText = list.items[index].text || '';
|
||||
this.setItemText(list, currentText + appendedText, index);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the given items to the end of the list.
|
||||
*/
|
||||
addItems(list, newItems, locale) {
|
||||
list.items = [...(list.items || []), ...formatItems(newItems, locale)];
|
||||
}
|
||||
};
|
||||
19
src/main/frontend/generated/jar-resources/selectConnector.js
Normal file
19
src/main/frontend/generated/jar-resources/selectConnector.js
Normal file
@@ -0,0 +1,19 @@
|
||||
window.Vaadin.Flow.selectConnector = {};
|
||||
window.Vaadin.Flow.selectConnector.initLazy = (select) => {
|
||||
// do not init this connector twice for the given select
|
||||
if (select.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
select.$connector = {};
|
||||
|
||||
select.renderer = (root) => {
|
||||
const listBox = select.querySelector('vaadin-select-list-box');
|
||||
if (listBox) {
|
||||
if (root.firstChild) {
|
||||
root.removeChild(root.firstChild);
|
||||
}
|
||||
root.appendChild(listBox);
|
||||
}
|
||||
};
|
||||
};
|
||||
175
src/main/frontend/generated/jar-resources/theme-util.js
Normal file
175
src/main/frontend/generated/jar-resources/theme-util.js
Normal file
@@ -0,0 +1,175 @@
|
||||
import stripCssComments from 'strip-css-comments';
|
||||
|
||||
// Safari 15 - 16.3, polyfilled
|
||||
const polyfilledSafari = CSSStyleSheet.toString().includes('document.createElement');
|
||||
|
||||
const createLinkReferences = (css, target) => {
|
||||
// Unresolved urls are written as '@import url(text);' or '@import "text";' to the css
|
||||
// media query can be present on @media tag or on @import directive after url
|
||||
// Note that with Vite production build there is no space between @import and "text"
|
||||
// [0] is the full match
|
||||
// [1] matches the media query
|
||||
// [2] matches the url
|
||||
// [3] matches the quote char surrounding in '@import "..."'
|
||||
// [4] matches the url in '@import "..."'
|
||||
// [5] matches media query on @import statement
|
||||
const importMatcher =
|
||||
/(?:@media\s(.+?))?(?:\s{)?\@import\s*(?:url\(\s*['"]?(.+?)['"]?\s*\)|(["'])((?:\\.|[^\\])*?)\3)([^;]*);(?:})?/g;
|
||||
|
||||
// Only cleanup if comment exist
|
||||
if (/\/\*(.|[\r\n])*?\*\//gm.exec(css) != null) {
|
||||
// clean up comments
|
||||
css = stripCssComments(css);
|
||||
}
|
||||
|
||||
var match;
|
||||
var styleCss = css;
|
||||
|
||||
// For each external url import add a link reference
|
||||
while ((match = importMatcher.exec(css)) !== null) {
|
||||
styleCss = styleCss.replace(match[0], '');
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = match[2] || match[4];
|
||||
const media = match[1] || match[5];
|
||||
if (media) {
|
||||
link.media = media;
|
||||
}
|
||||
// For target document append to head else append to target
|
||||
if (target === document) {
|
||||
document.head.appendChild(link);
|
||||
} else {
|
||||
target.appendChild(link);
|
||||
}
|
||||
}
|
||||
return styleCss;
|
||||
};
|
||||
|
||||
const addAdoptedStyleSafariPolyfill = (sheet, target, first) => {
|
||||
if (first) {
|
||||
target.adoptedStyleSheets = [sheet, ...target.adoptedStyleSheets];
|
||||
} else {
|
||||
target.adoptedStyleSheets = [...target.adoptedStyleSheets, sheet];
|
||||
}
|
||||
return () => {
|
||||
target.adoptedStyleSheets = target.adoptedStyleSheets.filter((ss) => ss !== sheet);
|
||||
};
|
||||
};
|
||||
|
||||
const addAdoptedStyle = (cssText, target, first) => {
|
||||
const sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync(cssText);
|
||||
if (polyfilledSafari) {
|
||||
return addAdoptedStyleSafariPolyfill(sheet, target, first);
|
||||
}
|
||||
if (first) {
|
||||
target.adoptedStyleSheets.splice(0, 0, sheet);
|
||||
} else {
|
||||
target.adoptedStyleSheets.push(sheet);
|
||||
}
|
||||
return () => {
|
||||
target.adoptedStyleSheets.splice(target.adoptedStyleSheets.indexOf(sheet), 1);
|
||||
};
|
||||
};
|
||||
|
||||
const addStyleTag = (cssText, referenceComment) => {
|
||||
const styleTag = document.createElement('style');
|
||||
styleTag.type = 'text/css';
|
||||
styleTag.textContent = cssText;
|
||||
|
||||
let beforeThis = undefined;
|
||||
if (referenceComment) {
|
||||
const comments = Array.from(document.head.childNodes).filter(elem => elem.nodeType === Node.COMMENT_NODE);
|
||||
const container = comments.find(comment => comment.data.trim() === referenceComment);
|
||||
if (container) {
|
||||
beforeThis = container;
|
||||
}
|
||||
}
|
||||
document.head.insertBefore(styleTag, beforeThis);
|
||||
return () => {
|
||||
styleTag.remove();
|
||||
};
|
||||
};
|
||||
|
||||
// target: Document | ShadowRoot
|
||||
export const injectGlobalCss = (css, referenceComment, target, first) => {
|
||||
if (target === document) {
|
||||
const hash = getHash(css);
|
||||
if (window.Vaadin.theme.injectedGlobalCss.indexOf(hash) !== -1) {
|
||||
return;
|
||||
}
|
||||
window.Vaadin.theme.injectedGlobalCss.push(hash);
|
||||
}
|
||||
const cssText = createLinkReferences(css, target);
|
||||
|
||||
// We avoid mixing style tags and adoptedStyleSheets to make override order clear
|
||||
if (target === document) {
|
||||
return addStyleTag(cssText, referenceComment);
|
||||
}
|
||||
|
||||
return addAdoptedStyle(cssText, target, first);
|
||||
};
|
||||
|
||||
window.Vaadin = window.Vaadin || {};
|
||||
window.Vaadin.theme = window.Vaadin.theme || {};
|
||||
window.Vaadin.theme.injectedGlobalCss = [];
|
||||
|
||||
const webcomponentGlobalCss = {
|
||||
css: [],
|
||||
importers: []
|
||||
};
|
||||
|
||||
export const injectGlobalWebcomponentCss = (css) => {
|
||||
webcomponentGlobalCss.css.push(css);
|
||||
webcomponentGlobalCss.importers.forEach(registrar => {
|
||||
registrar(css);
|
||||
});
|
||||
};
|
||||
|
||||
export const webcomponentGlobalCssInjector = (registrar) => {
|
||||
const registeredCss = [];
|
||||
const wrapper = (css) => {
|
||||
const hash = getHash(css);
|
||||
if (!registeredCss.includes(hash)) {
|
||||
registeredCss.push(hash);
|
||||
registrar(css);
|
||||
}
|
||||
};
|
||||
webcomponentGlobalCss.importers.push(wrapper);
|
||||
webcomponentGlobalCss.css.forEach(wrapper);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate a 32 bit FNV-1a hash
|
||||
* Found here: https://gist.github.com/vaiorabbit/5657561
|
||||
* Ref.: http://isthe.com/chongo/tech/comp/fnv/
|
||||
*
|
||||
* @param {string} str the input value
|
||||
* @returns {string} 32 bit (as 8 byte hex string)
|
||||
*/
|
||||
function hashFnv32a(str) {
|
||||
/*jshint bitwise:false */
|
||||
let i,
|
||||
l,
|
||||
hval = 0x811c9dc5;
|
||||
|
||||
for (i = 0, l = str.length; i < l; i++) {
|
||||
hval ^= str.charCodeAt(i);
|
||||
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
|
||||
}
|
||||
|
||||
// Convert to 8 digit hex string
|
||||
return ('0000000' + (hval >>> 0).toString(16)).substr(-8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a 64 bit hash for the given input.
|
||||
* Double hash is used to significantly lower the collision probability.
|
||||
*
|
||||
* @param {string} input value to get hash for
|
||||
* @returns {string} 64 bit (as 16 byte hex string)
|
||||
*/
|
||||
function getHash(input) {
|
||||
let h1 = hashFnv32a(input); // returns 32 bit (as 8 byte hex string)
|
||||
return h1 + hashFnv32a(h1 + input);
|
||||
}
|
||||
23
src/main/frontend/generated/jar-resources/tooltip.ts
Normal file
23
src/main/frontend/generated/jar-resources/tooltip.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Tooltip } from '@vaadin/tooltip/src/vaadin-tooltip.js';
|
||||
|
||||
const _window = window as any;
|
||||
_window.Vaadin ||= {};
|
||||
_window.Vaadin.Flow ||= {};
|
||||
_window.Vaadin.Flow.tooltip ||= {};
|
||||
|
||||
Object.assign(_window.Vaadin.Flow.tooltip, {
|
||||
setDefaultHideDelay: (hideDelay: number) => Tooltip.setDefaultHideDelay(hideDelay),
|
||||
setDefaultFocusDelay: (focusDelay: number) => Tooltip.setDefaultFocusDelay(focusDelay),
|
||||
setDefaultHoverDelay: (hoverDelay: number) => Tooltip.setDefaultHoverDelay(hoverDelay)
|
||||
});
|
||||
|
||||
const { defaultHideDelay, defaultFocusDelay, defaultHoverDelay } = _window.Vaadin.Flow.tooltip;
|
||||
if (defaultHideDelay) {
|
||||
Tooltip.setDefaultHideDelay(defaultHideDelay);
|
||||
}
|
||||
if (defaultFocusDelay) {
|
||||
Tooltip.setDefaultFocusDelay(defaultFocusDelay);
|
||||
}
|
||||
if (defaultHoverDelay) {
|
||||
Tooltip.setDefaultHoverDelay(defaultHoverDelay);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2000-2025 Vaadin Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
import { TextField } from '@vaadin/text-field/src/vaadin-text-field.js';
|
||||
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
||||
|
||||
let memoizedTemplate;
|
||||
|
||||
class BigDecimalField extends TextField {
|
||||
static get template() {
|
||||
if (!memoizedTemplate) {
|
||||
memoizedTemplate = super.template.cloneNode(true);
|
||||
memoizedTemplate.innerHTML += `<style>
|
||||
:host {
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
:host([dir="rtl"]) [part="input-field"] {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
:host([dir="rtl"]) [part="input-field"] ::slotted(input) {
|
||||
--_lumo-text-field-overflow-mask-image: linear-gradient(to left, transparent, #000 1.25em) !important;
|
||||
}
|
||||
</style>`;
|
||||
}
|
||||
return memoizedTemplate;
|
||||
}
|
||||
|
||||
static get is() {
|
||||
return 'vaadin-big-decimal-field';
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
_decimalSeparator: {
|
||||
type: String,
|
||||
value: '.',
|
||||
observer: '__decimalSeparatorChanged'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
this.inputElement.setAttribute('inputmode', 'decimal');
|
||||
}
|
||||
|
||||
__decimalSeparatorChanged(separator, oldSeparator) {
|
||||
this.allowedCharPattern = '[-+\\d' + separator + ']';
|
||||
|
||||
if (this.value && oldSeparator) {
|
||||
this.value = this.value.split(oldSeparator).join(separator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defineCustomElement(BigDecimalField);
|
||||
16
src/main/frontend/generated/jar-resources/vaadin-dev-tools/License.d.ts
vendored
Normal file
16
src/main/frontend/generated/jar-resources/vaadin-dev-tools/License.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { ServerMessage } from "./vaadin-dev-tools";
|
||||
export interface Product {
|
||||
name: string;
|
||||
version: string;
|
||||
}
|
||||
export interface ProductAndMessage {
|
||||
message: string;
|
||||
messageHtml?: string;
|
||||
product: Product;
|
||||
}
|
||||
export declare const findAll: (element: Element | ShadowRoot | Document, tags: string[]) => Element[];
|
||||
export declare const licenseCheckOk: (data: Product) => void;
|
||||
export declare const licenseCheckFailed: (data: ProductAndMessage) => void;
|
||||
export declare const licenseCheckNoKey: (data: ProductAndMessage) => void;
|
||||
export declare const handleLicenseMessage: (message: ServerMessage) => boolean;
|
||||
export declare const licenseInit: () => void;
|
||||
15
src/main/frontend/generated/jar-resources/vaadin-dev-tools/connection.d.ts
vendored
Normal file
15
src/main/frontend/generated/jar-resources/vaadin-dev-tools/connection.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export declare enum ConnectionStatus {
|
||||
ACTIVE = "active",
|
||||
INACTIVE = "inactive",
|
||||
UNAVAILABLE = "unavailable",
|
||||
ERROR = "error"
|
||||
}
|
||||
export declare abstract class Connection {
|
||||
static HEARTBEAT_INTERVAL: number;
|
||||
status: ConnectionStatus;
|
||||
onHandshake(): void;
|
||||
onConnectionError(_: string): void;
|
||||
onStatusChange(_: ConnectionStatus): void;
|
||||
setActive(yes: boolean): void;
|
||||
setStatus(status: ConnectionStatus): void;
|
||||
}
|
||||
8
src/main/frontend/generated/jar-resources/vaadin-dev-tools/live-reload-connection.d.ts
vendored
Normal file
8
src/main/frontend/generated/jar-resources/vaadin-dev-tools/live-reload-connection.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Connection } from './connection.js';
|
||||
export declare class LiveReloadConnection extends Connection {
|
||||
webSocket?: WebSocket;
|
||||
constructor(url: string);
|
||||
onReload(_strategy: string): void;
|
||||
handleMessage(msg: any): void;
|
||||
handleError(msg: any): void;
|
||||
}
|
||||
99
src/main/frontend/generated/jar-resources/vaadin-dev-tools/vaadin-dev-tools.d.ts
vendored
Normal file
99
src/main/frontend/generated/jar-resources/vaadin-dev-tools/vaadin-dev-tools.d.ts
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { LitElement } from 'lit';
|
||||
import { Product } from './License';
|
||||
import { ConnectionStatus } from './connection';
|
||||
/**
|
||||
* Plugin API for the dev tools window.
|
||||
*/
|
||||
export interface DevToolsInterface {
|
||||
send(command: string, data: any): void;
|
||||
}
|
||||
export interface MessageHandler {
|
||||
handleMessage(message: ServerMessage): boolean;
|
||||
}
|
||||
export interface ServerMessage {
|
||||
/**
|
||||
* The command
|
||||
*/
|
||||
command: string;
|
||||
/**
|
||||
* the data for the command
|
||||
*/
|
||||
data: any;
|
||||
}
|
||||
/**
|
||||
* To create and register a plugin, use e.g.
|
||||
* @example
|
||||
* export class MyTab extends LitElement implements MessageHandler {
|
||||
* render() {
|
||||
* return html`<div>Here I am</div>`;
|
||||
* }
|
||||
* }
|
||||
* customElements.define('my-tab', MyTab);
|
||||
*
|
||||
* const plugin: DevToolsPlugin = {
|
||||
* init: function (devToolsInterface: DevToolsInterface): void {
|
||||
* devToolsInterface.addTab('Tab title', 'my-tab')
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* (window as any).Vaadin.devToolsPlugins.push(plugin);
|
||||
*/
|
||||
export interface DevToolsPlugin {
|
||||
/**
|
||||
* Called once to initialize the plugin.
|
||||
*
|
||||
* @param devToolsInterface provides methods to interact with the dev tools
|
||||
*/
|
||||
init(devToolsInterface: DevToolsInterface): void;
|
||||
}
|
||||
export declare enum MessageType {
|
||||
LOG = "log",
|
||||
INFORMATION = "information",
|
||||
WARNING = "warning",
|
||||
ERROR = "error"
|
||||
}
|
||||
type DevToolsConf = {
|
||||
enable: boolean;
|
||||
url: string;
|
||||
backend?: string;
|
||||
liveReloadPort: number;
|
||||
token?: string;
|
||||
};
|
||||
export declare class VaadinDevTools extends LitElement {
|
||||
unhandledMessages: ServerMessage[];
|
||||
conf: DevToolsConf;
|
||||
static get styles(): import("lit").CSSResult[];
|
||||
static DISMISSED_NOTIFICATIONS_IN_LOCAL_STORAGE: string;
|
||||
static ACTIVE_KEY_IN_SESSION_STORAGE: string;
|
||||
static TRIGGERED_KEY_IN_SESSION_STORAGE: string;
|
||||
static TRIGGERED_COUNT_KEY_IN_SESSION_STORAGE: string;
|
||||
static AUTO_DEMOTE_NOTIFICATION_DELAY: number;
|
||||
static HOTSWAP_AGENT: string;
|
||||
static JREBEL: string;
|
||||
static SPRING_BOOT_DEVTOOLS: string;
|
||||
static BACKEND_DISPLAY_NAME: Record<string, string>;
|
||||
static get isActive(): boolean;
|
||||
frontendStatus: ConnectionStatus;
|
||||
javaStatus: ConnectionStatus;
|
||||
private root;
|
||||
componentPickActive: boolean;
|
||||
private javaConnection?;
|
||||
private frontendConnection?;
|
||||
private nextMessageId;
|
||||
private transitionDuration;
|
||||
elementTelemetry(): void;
|
||||
openWebSocketConnection(): void;
|
||||
tabHandleMessage(tabElement: HTMLElement, message: ServerMessage): boolean;
|
||||
handleFrontendMessage(message: ServerMessage): void;
|
||||
handleHmrMessage(message: ServerMessage): boolean;
|
||||
getDedicatedWebSocketUrl(): string | undefined;
|
||||
getSpringBootWebSocketUrl(location: any): string;
|
||||
connectedCallback(): void;
|
||||
initPlugin(plugin: DevToolsPlugin): Promise<void>;
|
||||
format(o: any): string;
|
||||
checkLicense(productInfo: Product): void;
|
||||
setActive(yes: boolean): void;
|
||||
render(): import("lit-html").TemplateResult<1>;
|
||||
setJavaLiveReloadActive(active: boolean): void;
|
||||
}
|
||||
export {};
|
||||
File diff suppressed because one or more lines are too long
13
src/main/frontend/generated/jar-resources/vaadin-dev-tools/websocket-connection.d.ts
vendored
Normal file
13
src/main/frontend/generated/jar-resources/vaadin-dev-tools/websocket-connection.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Connection } from './connection';
|
||||
export declare class WebSocketConnection extends Connection {
|
||||
static HEARTBEAT_INTERVAL: number;
|
||||
socket?: any;
|
||||
canSend: boolean;
|
||||
constructor(url: string);
|
||||
onReload(_strategy: string): void;
|
||||
onUpdate(_path: string, _content: string): void;
|
||||
onMessage(_message: any): void;
|
||||
handleMessage(msg: any): void;
|
||||
handleError(msg: any): void;
|
||||
send(command: string, data: any): void;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import '@vaadin/grid/vaadin-grid-column.js';
|
||||
import { GridColumn } from '@vaadin/grid/src/vaadin-grid-column.js';
|
||||
import { GridSelectionColumnBaseMixin } from '@vaadin/grid/src/vaadin-grid-selection-column-base-mixin.js';
|
||||
|
||||
export class GridFlowSelectionColumn extends GridSelectionColumnBaseMixin(GridColumn) {
|
||||
static get is() {
|
||||
return 'vaadin-grid-flow-selection-column';
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
/**
|
||||
* Override property to enable auto-width
|
||||
*/
|
||||
autoWidth: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Override property to set custom width
|
||||
*/
|
||||
width: {
|
||||
type: String,
|
||||
value: '56px'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Override method from `GridSelectionColumnBaseMixin` to add ID to select all
|
||||
* checkbox
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_defaultHeaderRenderer(root, _column) {
|
||||
super._defaultHeaderRenderer(root, _column);
|
||||
const checkbox = root.firstElementChild;
|
||||
if (checkbox) {
|
||||
checkbox.id = 'selectAllCheckbox';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override a method from `GridSelectionColumnBaseMixin` to handle the user
|
||||
* selecting all items.
|
||||
*
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
_selectAll() {
|
||||
this.selectAll = true;
|
||||
this.$server.selectAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override a method from `GridSelectionColumnBaseMixin` to handle the user
|
||||
* deselecting all items.
|
||||
*
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
_deselectAll() {
|
||||
this.selectAll = false;
|
||||
this.$server.deselectAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override a method from `GridSelectionColumnBaseMixin` to handle the user
|
||||
* selecting an item.
|
||||
*
|
||||
* @param {Object} item the item to select
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
_selectItem(item) {
|
||||
this.$server.setShiftKeyDown(this._shiftKeyDown);
|
||||
this._grid.$connector.doSelection([item], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override a method from `GridSelectionColumnBaseMixin` to handle the user
|
||||
* deselecting an item.
|
||||
*
|
||||
* @param {Object} item the item to deselect
|
||||
* @protected
|
||||
* @override
|
||||
*/
|
||||
_deselectItem(item) {
|
||||
this.$server.setShiftKeyDown(this._shiftKeyDown);
|
||||
this._grid.$connector.doDeselection([item], true);
|
||||
// Optimistically update select all state
|
||||
this.selectAll = false;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(GridFlowSelectionColumn.is, GridFlowSelectionColumn);
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Popover } from '@vaadin/popover/src/vaadin-popover.js';
|
||||
|
||||
const _window = window as any;
|
||||
_window.Vaadin ||= {};
|
||||
_window.Vaadin.Flow ||= {};
|
||||
_window.Vaadin.Flow.popover ||= {};
|
||||
|
||||
Object.assign(_window.Vaadin.Flow.popover, {
|
||||
setDefaultHideDelay: (hideDelay: number) => Popover.setDefaultHideDelay(hideDelay),
|
||||
setDefaultFocusDelay: (focusDelay: number) => Popover.setDefaultFocusDelay(focusDelay),
|
||||
setDefaultHoverDelay: (hoverDelay: number) => Popover.setDefaultHoverDelay(hoverDelay)
|
||||
});
|
||||
|
||||
const { defaultHideDelay, defaultFocusDelay, defaultHoverDelay } = _window.Vaadin.Flow.popover;
|
||||
|
||||
if (defaultHideDelay) {
|
||||
Popover.setDefaultHideDelay(defaultHideDelay);
|
||||
}
|
||||
|
||||
if (defaultFocusDelay) {
|
||||
Popover.setDefaultFocusDelay(defaultFocusDelay);
|
||||
}
|
||||
|
||||
if (defaultHoverDelay) {
|
||||
Popover.setDefaultHoverDelay(defaultHoverDelay);
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
// map from unicode eastern arabic number characters to arabic numbers
|
||||
const EASTERN_ARABIC_DIGIT_MAP = {
|
||||
'\\u0660': '0',
|
||||
'\\u0661': '1',
|
||||
'\\u0662': '2',
|
||||
'\\u0663': '3',
|
||||
'\\u0664': '4',
|
||||
'\\u0665': '5',
|
||||
'\\u0666': '6',
|
||||
'\\u0667': '7',
|
||||
'\\u0668': '8',
|
||||
'\\u0669': '9'
|
||||
};
|
||||
|
||||
/**
|
||||
* Escapes the given string so it can be safely used in a regexp.
|
||||
*
|
||||
* @param {string} string
|
||||
* @return {string}
|
||||
*/
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses eastern arabic number characters to arabic numbers (0-9)
|
||||
*
|
||||
* @param {string} digits
|
||||
* @return {string}
|
||||
*/
|
||||
function parseEasternArabicDigits(digits) {
|
||||
return digits.replace(/[\u0660-\u0669]/g, function (char) {
|
||||
const unicode = '\\u0' + char.charCodeAt(0).toString(16);
|
||||
return EASTERN_ARABIC_DIGIT_MAP[unicode];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @param {Date} testTime
|
||||
* @return {string | null}
|
||||
*/
|
||||
function getAmOrPmString(locale, testTime) {
|
||||
const testTimeString = testTime.toLocaleTimeString(locale);
|
||||
|
||||
// AM/PM string is anything from one letter in eastern arabic to standard two letters,
|
||||
// to having space in between, dots ...
|
||||
// cannot disqualify whitespace since some locales use a. m. / p. m.
|
||||
// TODO when more scripts support is added (than Arabic), need to exclude those numbers too
|
||||
const amOrPmRegExp = /[^\d\u0660-\u0669]/;
|
||||
|
||||
const matches =
|
||||
// In most locales, the time ends with AM/PM:
|
||||
testTimeString.match(new RegExp(`${amOrPmRegExp.source}+$`, 'g')) ||
|
||||
// In some locales, the time starts with AM/PM e.g in Chinese:
|
||||
testTimeString.match(new RegExp(`^${amOrPmRegExp.source}+`, 'g'));
|
||||
|
||||
return matches && matches[0].trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @return {string | null}
|
||||
*/
|
||||
export function getSeparator(locale) {
|
||||
let timeString = TEST_PM_TIME.toLocaleTimeString(locale);
|
||||
|
||||
// Since the next regex picks first non-number-whitespace,
|
||||
// need to discard possible PM from beginning (eg. chinese locale)
|
||||
const pmString = getPmString(locale);
|
||||
if (pmString && timeString.startsWith(pmString)) {
|
||||
timeString = timeString.replace(pmString, '');
|
||||
}
|
||||
|
||||
const matches = timeString.match(/[^\u0660-\u0669\s\d]/);
|
||||
return matches && matches[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for either an AM or PM token in the given time string
|
||||
* depending on what is provided in `amOrPmString`.
|
||||
*
|
||||
* The search is case and space insensitive.
|
||||
*
|
||||
* @example
|
||||
* `searchAmOrPmToken('1 P M', 'PM')` => `'P M'`
|
||||
*
|
||||
* @example
|
||||
* `searchAmOrPmToken('1 a.m.', 'A. M.')` => `a.m.`
|
||||
*
|
||||
* @param {string} timeString
|
||||
* @param {string} amOrPmString
|
||||
* @return {string | null}
|
||||
*/
|
||||
export function searchAmOrPmToken(timeString, amOrPmString) {
|
||||
if (!amOrPmString) return null;
|
||||
|
||||
// Create a regexp string for searching for AM/PM without space-sensitivity.
|
||||
const tokenRegExpString = amOrPmString.split(/\s*/).map(escapeRegExp).join('\\s*');
|
||||
|
||||
// Create a regexp without case-sensitivity.
|
||||
const tokenRegExp = new RegExp(tokenRegExpString, 'i');
|
||||
|
||||
// Match the regexp against the time string.
|
||||
const tokenMatches = timeString.match(tokenRegExp);
|
||||
if (tokenMatches) {
|
||||
return tokenMatches[0];
|
||||
}
|
||||
}
|
||||
|
||||
export const TEST_PM_TIME = new Date('August 19, 1975 23:15:30');
|
||||
|
||||
export const TEST_AM_TIME = new Date('August 19, 1975 05:15:30');
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @return {string}
|
||||
*/
|
||||
export function getPmString(locale) {
|
||||
return getAmOrPmString(locale, TEST_PM_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @return {string}
|
||||
*/
|
||||
export function getAmString(locale) {
|
||||
return getAmOrPmString(locale, TEST_AM_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} digits
|
||||
* @return {number}
|
||||
*/
|
||||
export function parseDigitsIntoInteger(digits) {
|
||||
return parseInt(parseEasternArabicDigits(digits));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} milliseconds
|
||||
* @return {number}
|
||||
*/
|
||||
export function parseMillisecondsIntoInteger(milliseconds) {
|
||||
milliseconds = parseEasternArabicDigits(milliseconds);
|
||||
// digits are either .1 .01 or .001 so need to "shift"
|
||||
if (milliseconds.length === 1) {
|
||||
milliseconds += '00';
|
||||
} else if (milliseconds.length === 2) {
|
||||
milliseconds += '0';
|
||||
}
|
||||
return parseInt(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} timeString
|
||||
* @param {number} milliseconds
|
||||
* @param {string} amString
|
||||
* @param {string} pmString
|
||||
* @return {string}
|
||||
*/
|
||||
export function formatMilliseconds(timeString, milliseconds, amString, pmString) {
|
||||
// might need to inject milliseconds between seconds and AM/PM
|
||||
let cleanedTimeString = timeString;
|
||||
if (timeString.endsWith(amString)) {
|
||||
cleanedTimeString = timeString.replace(' ' + amString, '');
|
||||
} else if (timeString.endsWith(pmString)) {
|
||||
cleanedTimeString = timeString.replace(' ' + pmString, '');
|
||||
}
|
||||
if (milliseconds) {
|
||||
let millisecondsString = milliseconds < 10 ? '0' : '';
|
||||
millisecondsString += milliseconds < 100 ? '0' : '';
|
||||
millisecondsString += milliseconds;
|
||||
cleanedTimeString += '.' + millisecondsString;
|
||||
} else {
|
||||
cleanedTimeString += '.000';
|
||||
}
|
||||
if (timeString.endsWith(amString)) {
|
||||
cleanedTimeString = cleanedTimeString + ' ' + amString;
|
||||
} else if (timeString.endsWith(pmString)) {
|
||||
cleanedTimeString = cleanedTimeString + ' ' + pmString;
|
||||
}
|
||||
return cleanedTimeString;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
import {
|
||||
TEST_PM_TIME,
|
||||
formatMilliseconds,
|
||||
parseMillisecondsIntoInteger,
|
||||
parseDigitsIntoInteger,
|
||||
getAmString,
|
||||
getPmString,
|
||||
getSeparator,
|
||||
searchAmOrPmToken
|
||||
} from './helpers.js';
|
||||
import { parseISOTime } from '@vaadin/time-picker/src/vaadin-time-picker-helper.js';
|
||||
|
||||
// Execute callback when predicate returns true.
|
||||
// Try again later if predicate returns false.
|
||||
function when(predicate, callback, timeout = 0) {
|
||||
if (predicate()) {
|
||||
callback();
|
||||
} else {
|
||||
setTimeout(() => when(predicate, callback, 200), timeout);
|
||||
}
|
||||
}
|
||||
|
||||
function parseISO(text) {
|
||||
// The default i18n parser of the web component is ISO 8601 compliant.
|
||||
const timeObject = parseISOTime(text);
|
||||
|
||||
// The web component returns an object with string values
|
||||
// while the connector expects number values.
|
||||
return {
|
||||
hours: parseInt(timeObject.hours || 0),
|
||||
minutes: parseInt(timeObject.minutes || 0),
|
||||
seconds: parseInt(timeObject.seconds || 0),
|
||||
milliseconds: parseInt(timeObject.milliseconds || 0)
|
||||
};
|
||||
}
|
||||
|
||||
window.Vaadin.Flow.timepickerConnector = {};
|
||||
window.Vaadin.Flow.timepickerConnector.initLazy = (timepicker) => {
|
||||
// Check whether the connector was already initialized for the timepicker
|
||||
if (timepicker.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
timepicker.$connector = {};
|
||||
|
||||
timepicker.$connector.setLocale = (locale) => {
|
||||
// capture previous value if any
|
||||
let previousValueObject;
|
||||
if (timepicker.value && timepicker.value !== '') {
|
||||
previousValueObject = parseISO(timepicker.value);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check whether the locale is supported by the browser or not
|
||||
TEST_PM_TIME.toLocaleTimeString(locale);
|
||||
} catch (e) {
|
||||
locale = 'en-US';
|
||||
// FIXME should do a callback for server to throw an exception ?
|
||||
throw new Error(
|
||||
'vaadin-time-picker: The locale ' + locale + ' is not supported, falling back to default locale setting(en-US).'
|
||||
);
|
||||
}
|
||||
|
||||
// 1. 24 or 12 hour clock, if latter then what are the am/pm strings ?
|
||||
const pmString = getPmString(locale);
|
||||
const amString = getAmString(locale);
|
||||
|
||||
// 2. What is the separator ?
|
||||
const separator = getSeparator(locale);
|
||||
|
||||
const includeSeconds = function () {
|
||||
return timepicker.step && timepicker.step < 60;
|
||||
};
|
||||
|
||||
const includeMilliSeconds = function () {
|
||||
return timepicker.step && timepicker.step < 1;
|
||||
};
|
||||
|
||||
let cachedTimeString;
|
||||
let cachedTimeObject;
|
||||
|
||||
timepicker.i18n = {
|
||||
formatTime(timeObject) {
|
||||
if (!timeObject) return;
|
||||
|
||||
const timeToBeFormatted = new Date();
|
||||
timeToBeFormatted.setHours(timeObject.hours);
|
||||
timeToBeFormatted.setMinutes(timeObject.minutes);
|
||||
timeToBeFormatted.setSeconds(timeObject.seconds !== undefined ? timeObject.seconds : 0);
|
||||
|
||||
// the web component expects the correct granularity used for the time string,
|
||||
// thus need to format the time object in correct granularity by passing the format options
|
||||
let localeTimeString = timeToBeFormatted.toLocaleTimeString(locale, {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: includeSeconds() ? 'numeric' : undefined
|
||||
});
|
||||
|
||||
// milliseconds not part of the time format API
|
||||
if (includeMilliSeconds()) {
|
||||
localeTimeString = formatMilliseconds(localeTimeString, timeObject.milliseconds, amString, pmString);
|
||||
}
|
||||
|
||||
return localeTimeString;
|
||||
},
|
||||
|
||||
parseTime(timeString) {
|
||||
if (timeString && timeString === cachedTimeString && cachedTimeObject) {
|
||||
return cachedTimeObject;
|
||||
}
|
||||
|
||||
if (!timeString) {
|
||||
// when nothing is returned, the component shows the invalid state for the input
|
||||
return;
|
||||
}
|
||||
|
||||
const amToken = searchAmOrPmToken(timeString, amString);
|
||||
const pmToken = searchAmOrPmToken(timeString, pmString);
|
||||
|
||||
const numbersOnlyTimeString = timeString
|
||||
.replace(amToken || '', '')
|
||||
.replace(pmToken || '', '')
|
||||
.trim();
|
||||
|
||||
// A regexp that allows to find the numbers with optional separator and continuing searching after it.
|
||||
const numbersRegExp = new RegExp('([\\d\\u0660-\\u0669]){1,2}(?:' + separator + ')?', 'g');
|
||||
|
||||
let hours = numbersRegExp.exec(numbersOnlyTimeString);
|
||||
if (hours) {
|
||||
hours = parseDigitsIntoInteger(hours[0].replace(separator, ''));
|
||||
// handle 12 am -> 0
|
||||
// do not do anything if am & pm are not used or if those are the same,
|
||||
// as with locale bg-BG there is always ч. at the end of the time
|
||||
if (amToken !== pmToken) {
|
||||
if (hours === 12 && amToken) {
|
||||
hours = 0;
|
||||
}
|
||||
if (hours !== 12 && pmToken) {
|
||||
hours += 12;
|
||||
}
|
||||
}
|
||||
const minutes = numbersRegExp.exec(numbersOnlyTimeString);
|
||||
const seconds = minutes && numbersRegExp.exec(numbersOnlyTimeString);
|
||||
// detecting milliseconds from input, expects am/pm removed from end, eg. .0 or .00 or .000
|
||||
const millisecondRegExp = /[[\.][\d\u0660-\u0669]{1,3}$/;
|
||||
// reset to end or things can explode
|
||||
let milliseconds = seconds && includeMilliSeconds() && millisecondRegExp.exec(numbersOnlyTimeString);
|
||||
// handle case where last numbers are seconds and . is the separator (invalid regexp match)
|
||||
if (milliseconds && milliseconds['index'] <= seconds['index']) {
|
||||
milliseconds = undefined;
|
||||
}
|
||||
// hours is a number at this point, others are either arrays or null
|
||||
// the string in [0] from the arrays includes the separator too
|
||||
cachedTimeObject = hours !== undefined && {
|
||||
hours: hours,
|
||||
minutes: minutes ? parseDigitsIntoInteger(minutes[0].replace(separator, '')) : 0,
|
||||
seconds: seconds ? parseDigitsIntoInteger(seconds[0].replace(separator, '')) : 0,
|
||||
milliseconds:
|
||||
minutes && seconds && milliseconds ? parseMillisecondsIntoInteger(milliseconds[0].replace('.', '')) : 0
|
||||
};
|
||||
cachedTimeString = timeString;
|
||||
return cachedTimeObject;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (previousValueObject) {
|
||||
when(
|
||||
() => timepicker.$,
|
||||
() => {
|
||||
const newValue = timepicker.i18n.formatTime(previousValueObject);
|
||||
// FIXME works but uses private API, needs fixes in web component
|
||||
if (timepicker.inputElement.value !== newValue) {
|
||||
timepicker.inputElement.value = newValue;
|
||||
timepicker.$.comboBox.value = newValue;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,152 @@
|
||||
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
||||
import { timeOut } from '@vaadin/component-base/src/async.js';
|
||||
|
||||
window.Vaadin.Flow.virtualListConnector = {
|
||||
initLazy: function (list) {
|
||||
// Check whether the connector was already initialized for the virtual list
|
||||
if (list.$connector) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extraItemsBuffer = 20;
|
||||
|
||||
let lastRequestedRange = [0, 0];
|
||||
|
||||
list.$connector = {};
|
||||
list.$connector.placeholderItem = { __placeholder: true };
|
||||
|
||||
list.itemAccessibleNameGenerator = (item) => item && item.accessibleName;
|
||||
|
||||
const updateRequestedItem = function () {
|
||||
/*
|
||||
* TODO virtual list seems to do a small index adjustment after scrolling
|
||||
* has stopped. This causes a redundant request to be sent to make a
|
||||
* corresponding minimal change to the buffer. We should avoid these
|
||||
* requests by making the logic skip doing a request if the available
|
||||
* buffer is within some tolerance compared to the requested buffer.
|
||||
*/
|
||||
const visibleIndexes = [...list.children]
|
||||
.filter((el) => '__virtualListIndex' in el)
|
||||
.map((el) => el.__virtualListIndex);
|
||||
const firstNeededItem = Math.min(...visibleIndexes);
|
||||
const lastNeededItem = Math.max(...visibleIndexes);
|
||||
|
||||
let first = Math.max(0, firstNeededItem - extraItemsBuffer);
|
||||
let last = Math.min(lastNeededItem + extraItemsBuffer, list.items.length);
|
||||
|
||||
if (lastRequestedRange[0] != first || lastRequestedRange[1] != last) {
|
||||
lastRequestedRange = [first, last];
|
||||
const count = 1 + last - first;
|
||||
list.$server.setRequestedRange(first, count);
|
||||
}
|
||||
};
|
||||
|
||||
const scheduleUpdateRequest = function () {
|
||||
list.__requestDebounce = Debouncer.debounce(list.__requestDebounce, timeOut.after(50), updateRequestedItem);
|
||||
};
|
||||
|
||||
requestAnimationFrame(() => updateRequestedItem);
|
||||
|
||||
// Add an observer function that will invoke on virtualList.renderer property
|
||||
// change and then patches it with a wrapper renderer
|
||||
list.patchVirtualListRenderer = function () {
|
||||
if (!list.renderer || list.renderer.__virtualListConnectorPatched) {
|
||||
// The list either doesn't have a renderer yet or it's already been patched
|
||||
return;
|
||||
}
|
||||
|
||||
const originalRenderer = list.renderer;
|
||||
|
||||
const renderer = (root, list, model) => {
|
||||
root.__virtualListIndex = model.index;
|
||||
|
||||
if (model.item === undefined) {
|
||||
if (list.$connector.placeholderElement) {
|
||||
// ComponentRenderer
|
||||
if (!root.__hasComponentRendererPlaceholder) {
|
||||
// The root was previously rendered by the ComponentRenderer. Clear and add a placeholder.
|
||||
root.innerHTML = '';
|
||||
delete root._$litPart$;
|
||||
root.appendChild(list.$connector.placeholderElement.cloneNode(true));
|
||||
root.__hasComponentRendererPlaceholder = true;
|
||||
}
|
||||
} else {
|
||||
// LitRenderer
|
||||
originalRenderer.call(list, root, list, {
|
||||
...model,
|
||||
item: list.$connector.placeholderItem
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (root.__hasComponentRendererPlaceholder) {
|
||||
// The root was previously populated with a placeholder. Clear it.
|
||||
root.innerHTML = '';
|
||||
root.__hasComponentRendererPlaceholder = false;
|
||||
}
|
||||
|
||||
originalRenderer.call(list, root, list, model);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we need to do anything once things have settled down.
|
||||
* This method is called multiple times in sequence for the same user
|
||||
* action, but we only want to do the check once.
|
||||
*/
|
||||
scheduleUpdateRequest();
|
||||
};
|
||||
renderer.__virtualListConnectorPatched = true;
|
||||
renderer.__rendererId = originalRenderer.__rendererId;
|
||||
|
||||
list.renderer = renderer;
|
||||
};
|
||||
|
||||
list._createPropertyObserver('renderer', 'patchVirtualListRenderer', true);
|
||||
list.patchVirtualListRenderer();
|
||||
|
||||
list.items = [];
|
||||
|
||||
list.$connector.set = function (index, items) {
|
||||
list.items.splice(index, items.length, ...items);
|
||||
list.items = [...list.items];
|
||||
};
|
||||
|
||||
list.$connector.clear = function (index, length) {
|
||||
// How many items, starting from "index", should be set as undefined
|
||||
const clearCount = Math.min(length, list.items.length - index);
|
||||
list.$connector.set(index, [...Array(clearCount)]);
|
||||
};
|
||||
|
||||
list.$connector.updateData = function (items) {
|
||||
const updatedItemsMap = items.reduce((map, item) => {
|
||||
map[item.key] = item;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
list.items = list.items.map((item) => {
|
||||
// Items can be undefined if they are outside the viewport
|
||||
if (!item) {
|
||||
return item;
|
||||
}
|
||||
// Replace existing item with updated item,
|
||||
// return existing item as fallback if it was not updated
|
||||
return updatedItemsMap[item.key] || item;
|
||||
});
|
||||
};
|
||||
|
||||
list.$connector.updateSize = function (newSize) {
|
||||
const delta = newSize - list.items.length;
|
||||
if (delta > 0) {
|
||||
list.items = [...list.items, ...Array(delta)];
|
||||
} else if (delta < 0) {
|
||||
list.items = list.items.slice(0, newSize);
|
||||
}
|
||||
};
|
||||
|
||||
list.$connector.setPlaceholderItem = function (placeholderItem = {}, appId) {
|
||||
placeholderItem.__placeholder = true;
|
||||
list.$connector.placeholderItem = placeholderItem;
|
||||
const nodeId = Object.entries(placeholderItem).find(([key]) => key.endsWith('_nodeid'));
|
||||
list.$connector.placeholderElement = nodeId ? Vaadin.Flow.clients[appId].getByNodeId(nodeId[1]) : null;
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user