@ethlete/query-devtools 1.0.0-next.16 → 1.0.0-next.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0-next.18
4
+
5
+ ### Minor Changes
6
+
7
+ - `provideQueryDevtools({ ui: () => import('@ethlete/query-devtools/lazy') })` mounts the devtools once the app has rendered, with no template tag. `@ethlete/query-devtools/lazy` exports `mountQueryDevtools`.
8
+
9
+ ## 1.0.0-next.17
10
+
11
+ ### Patch Changes
12
+
13
+ - The devtools panel, toggle and pills hide under `navigator.webdriver`. Set `provideQueryDevtools({ showInAutomation: true })` to keep them.
14
+ - The toggle entry point no longer imports the `@ethlete/components` barrel, so the lazy shell adds no components code to the initial bundle of an application.
15
+
3
16
  ## 1.0.0-next.16
4
17
 
5
18
  ### Minor Changes
@@ -1,86 +1,59 @@
1
- import { DOCUMENT } from '@angular/common';
2
- import * as i0 from '@angular/core';
3
- import { inject, signal, computed, DestroyRef, ViewEncapsulation, Component } from '@angular/core';
4
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
- import { setQueryDevtoolsUiMounted } from '@ethlete/query';
6
- import { isQueryDevtoolsEnabled, queryDevtoolsFaults, queryDevtoolsTokenTtls, queryDevtoolsArmedMocks, queryDevtoolsEntries } from '@ethlete/query/devtools-contract';
7
- import { fromEvent, filter, tap } from 'rxjs';
8
- import { ɵwasQueryDevtoolsOpen as _wasQueryDevtoolsOpen, isQueryDevtoolsShortcut, QueryDevtoolsToggleComponent } from '@ethlete/query-devtools/toggle';
9
-
1
+ import { DOCUMENT } from "@angular/common";
2
+ import * as i0 from "@angular/core";
3
+ import { ApplicationRef, Component, DestroyRef, RendererFactory2, ViewEncapsulation, computed, createComponent, inject, signal } from "@angular/core";
4
+ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
5
+ import { setQueryDevtoolsUiMounted } from "@ethlete/query";
6
+ import { isQueryDevtoolsEnabled, isQueryDevtoolsHiddenInAutomation, queryDevtoolsArmedMocks, queryDevtoolsEntries, queryDevtoolsFaults, queryDevtoolsTokenTtls } from "@ethlete/query/devtools-contract";
7
+ import { filter, fromEvent, tap } from "rxjs";
8
+ import { QueryDevtoolsToggleComponent, isQueryDevtoolsShortcut, ɵwasQueryDevtoolsOpen } from "@ethlete/query-devtools/toggle";
10
9
  let warnedMissingProvider = false;
11
- /**
12
- * The query devtools behind a deferred load: renders only the floating toggle button until the panel is
13
- * first asked for, then downloads `<et-query-devtools>` as its own chunk and hands over. Use it instead
14
- * of `<et-query-devtools>` to keep the panel out of the bundle an application ships to its users.
15
- *
16
- * Without `provideQueryDevtools()` it renders nothing at all - no toggle, no shortcut, and the panel
17
- * chunk is never requested - so it can be left mounted in a production build.
18
- *
19
- * Everything else is identical - the same toggle, the same `Ctrl/Cmd + Alt + Q` shortcut, and a panel
20
- * that was open when the tab last stored its state comes back open without a click.
21
- *
22
- * @example
23
- * ```html
24
- * <et-query-devtools-lazy />
25
- * ```
26
- */
27
- class QueryDevtoolsLazyComponent {
28
- constructor() {
29
- this.document = inject(DOCUMENT);
30
- /**
31
- * Whether `provideQueryDevtools()` is in the application. Everything else here is gated on it - the
32
- * stored view state read, the shortcut listener and the template - so a build that ships the shell
33
- * without the provider renders nothing and can never load the panel.
34
- */
35
- this.enabled = isQueryDevtoolsEnabled();
36
- /**
37
- * Whether the panel is wanted. Whether it was already open has to be answered before the panel exists,
38
- * which is why the stored view state is read here rather than asked of the panel.
39
- */
40
- this.load = signal(this.enabled && _wasQueryDevtoolsOpen(), /* @ts-ignore */
41
- ...(ngDevMode ? [{ debugName: "load" }] : /* istanbul ignore next */ []));
42
- /** A restored panel opens because it was open; one that was clicked open has to be told to. */
43
- this.openOnLoad = signal(false, /* @ts-ignore */
44
- ...(ngDevMode ? [{ debugName: "openOnLoad" }] : /* istanbul ignore next */ []));
45
- /**
46
- * Whether anything armed is changing what the app does, for the dot on the closed toggle. The panel's
47
- * own badge is per-query and finer-grained; this covers what can already be armed before the panel has
48
- * ever been loaded - overrides and mocks restored from a previous page load, and anything an app or a
49
- * test armed through the API.
50
- */
51
- this.tampered = computed(() => Object.keys(queryDevtoolsFaults()).length > 0 ||
52
- Object.keys(queryDevtoolsTokenTtls()).length > 0 ||
53
- queryDevtoolsArmedMocks().size > 0 ||
54
- queryDevtoolsEntries().some((entry) => (entry.overrides?.list().length ?? 0) > 0), /* @ts-ignore */
55
- ...(ngDevMode ? [{ debugName: "tampered" }] : /* istanbul ignore next */ []));
56
- if (!this.enabled) {
57
- if (ngDevMode && !warnedMissingProvider) {
58
- warnedMissingProvider = true;
59
- console.warn("<et-query-devtools-lazy>: provideQueryDevtools() is not in the application providers, so the devtools render nothing. Add it to bootstrapApplication's providers.");
60
- }
61
- return;
62
- }
63
- setQueryDevtoolsUiMounted(true);
64
- inject(DestroyRef).onDestroy(() => setQueryDevtoolsUiMounted(false));
65
- // The same shortcut the panel installs, for the one press that has to happen before it exists. Once
66
- // the panel is loaded it owns the key, so this stops at the first press it handles.
67
- fromEvent(this.document, 'keydown')
68
- .pipe(filter(() => !this.load()), filter(isQueryDevtoolsShortcut), tap((e) => {
69
- e.preventDefault();
70
- this.open();
71
- }), takeUntilDestroyed())
72
- .subscribe();
73
- }
74
- open() {
75
- this.openOnLoad.set(true);
76
- this.load.set(true);
77
- }
78
- /** Angular never retries a failed `@defer`, so only a page load can fetch the panel chunk again. */
79
- reload() {
80
- this.document.defaultView?.location.reload();
81
- }
82
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: QueryDevtoolsLazyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
83
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: QueryDevtoolsLazyComponent, isStandalone: true, selector: "et-query-devtools-lazy", ngImport: i0, template: `
10
+ var QueryDevtoolsLazyComponent = class QueryDevtoolsLazyComponent {
11
+ constructor() {
12
+ this.document = inject(DOCUMENT);
13
+ this.enabled = isQueryDevtoolsEnabled() && !isQueryDevtoolsHiddenInAutomation();
14
+ this.load = signal(this.enabled && ɵwasQueryDevtoolsOpen(), ...ngDevMode ? [{ debugName: "load" }] : /* istanbul ignore next */ []);
15
+ this.openOnLoad = signal(false, ...ngDevMode ? [{ debugName: "openOnLoad" }] : /* istanbul ignore next */ []);
16
+ this.tampered = computed(() => Object.keys(queryDevtoolsFaults()).length > 0 || Object.keys(queryDevtoolsTokenTtls()).length > 0 || queryDevtoolsArmedMocks().size > 0 || queryDevtoolsEntries().some((entry) => (entry.overrides?.list().length ?? 0) > 0), ...ngDevMode ? [{ debugName: "tampered" }] : /* istanbul ignore next */ []);
17
+ if (!this.enabled) {
18
+ if (ngDevMode && !warnedMissingProvider && !isQueryDevtoolsEnabled()) {
19
+ warnedMissingProvider = true;
20
+ console.warn("<et-query-devtools-lazy>: provideQueryDevtools() is not in the application providers, so the devtools render nothing. Add it to bootstrapApplication's providers.");
21
+ }
22
+ return;
23
+ }
24
+ setQueryDevtoolsUiMounted(true);
25
+ inject(DestroyRef).onDestroy(() => setQueryDevtoolsUiMounted(false));
26
+ fromEvent(this.document, "keydown").pipe(filter(() => !this.load()), filter(isQueryDevtoolsShortcut), tap((e) => {
27
+ e.preventDefault();
28
+ this.open();
29
+ }), takeUntilDestroyed()).subscribe();
30
+ }
31
+ open() {
32
+ this.openOnLoad.set(true);
33
+ this.load.set(true);
34
+ }
35
+ reload() {
36
+ this.document.defaultView?.location.reload();
37
+ }
38
+ static {
39
+ this.ɵfac = i0.ɵɵngDeclareFactory({
40
+ minVersion: "12.0.0",
41
+ version: "22.2.3",
42
+ ngImport: i0,
43
+ type: QueryDevtoolsLazyComponent,
44
+ deps: [],
45
+ target: i0.ɵɵFactoryTarget.Component
46
+ });
47
+ }
48
+ static {
49
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
50
+ minVersion: "17.0.0",
51
+ version: "22.2.3",
52
+ type: QueryDevtoolsLazyComponent,
53
+ isStandalone: true,
54
+ selector: "et-query-devtools-lazy",
55
+ ngImport: i0,
56
+ template: `
84
57
  @if (enabled) {
85
58
  @defer (when load()) {
86
59
  <et-query-devtools [startOpen]="openOnLoad()" />
@@ -92,15 +65,32 @@ class QueryDevtoolsLazyComponent {
92
65
  <et-query-devtools-toggle [tampered]="tampered()" (openChange)="reload()" loadFailed />
93
66
  }
94
67
  }
95
- `, isInline: true, dependencies: [{ kind: "component", type: QueryDevtoolsToggleComponent, selector: "et-query-devtools-toggle", inputs: ["tampered", "loadFailed"], outputs: ["openChange"] }], encapsulation: i0.ViewEncapsulation.None, deferBlockDependencies: [() => [/* @ts-ignore */
96
- import('@ethlete/query-devtools').then(m => m.QueryDevtoolsComponent)]] }); }
97
- }
98
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ngImport: i0, type: QueryDevtoolsLazyComponent, resolveDeferredDeps: () => [/* @ts-ignore */
99
- import('@ethlete/query-devtools').then(m => m.QueryDevtoolsComponent)], resolveMetadata: QueryDevtoolsComponent => ({ decorators: [{
100
- type: Component,
101
- args: [{
102
- selector: 'et-query-devtools-lazy',
103
- template: `
68
+ `,
69
+ isInline: true,
70
+ dependencies: [{
71
+ kind: "component",
72
+ type: QueryDevtoolsToggleComponent,
73
+ selector: "et-query-devtools-toggle",
74
+ inputs: ["tampered", "loadFailed"],
75
+ outputs: ["openChange"]
76
+ }],
77
+ encapsulation: i0.ViewEncapsulation.None,
78
+ deferBlockDependencies: [() => [import("@ethlete/query-devtools").then((m) => m.QueryDevtoolsComponent)]]
79
+ });
80
+ }
81
+ };
82
+ i0.ɵɵngDeclareClassMetadataAsync({
83
+ minVersion: "18.0.0",
84
+ version: "22.2.3",
85
+ ngImport: i0,
86
+ type: QueryDevtoolsLazyComponent,
87
+ resolveDeferredDeps: () => [import("@ethlete/query-devtools").then((m) => m.QueryDevtoolsComponent)],
88
+ resolveMetadata: (QueryDevtoolsComponent) => ({
89
+ decorators: [{
90
+ type: Component,
91
+ args: [{
92
+ selector: "et-query-devtools-lazy",
93
+ template: `
104
94
  @if (enabled) {
105
95
  @defer (when load()) {
106
96
  <et-query-devtools [startOpen]="openOnLoad()" />
@@ -113,14 +103,27 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.6", ng
113
103
  }
114
104
  }
115
105
  `,
116
- encapsulation: ViewEncapsulation.None,
117
- imports: [QueryDevtoolsComponent, QueryDevtoolsToggleComponent],
118
- }]
119
- }], ctorParameters: () => [], propDecorators: null }) });
120
-
121
- /**
122
- * Generated bundle index. Do not edit.
123
- */
106
+ encapsulation: ViewEncapsulation.None,
107
+ imports: [QueryDevtoolsComponent, QueryDevtoolsToggleComponent]
108
+ }]
109
+ }],
110
+ ctorParameters: () => [],
111
+ propDecorators: null
112
+ })
113
+ });
114
+ const mountQueryDevtools = (injector) => {
115
+ const host = injector.get(ApplicationRef);
116
+ const renderer = injector.get(RendererFactory2).createRenderer(null, null);
117
+ const element = renderer.createElement("et-query-devtools-lazy");
118
+ renderer.appendChild(injector.get(DOCUMENT).body, element);
119
+ const ref = createComponent(QueryDevtoolsLazyComponent, {
120
+ environmentInjector: injector,
121
+ hostElement: element
122
+ });
123
+ host.attachView(ref.hostView);
124
+ injector.get(DestroyRef).onDestroy(() => ref.destroy());
125
+ return ref;
126
+ };
127
+ export { QueryDevtoolsLazyComponent, mountQueryDevtools };
124
128
 
125
- export { QueryDevtoolsLazyComponent };
126
- //# sourceMappingURL=ethlete-query-devtools-lazy.mjs.map
129
+ //# sourceMappingURL=ethlete-query-devtools-lazy.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ethlete-query-devtools-lazy.mjs","sources":["../../../../libs/query-devtools/lazy/query-devtools-lazy.component.ts","../../../../libs/query-devtools/lazy/ethlete-query-devtools-lazy.ts"],"sourcesContent":["import { DOCUMENT } from '@angular/common';\nimport { Component, computed, DestroyRef, inject, signal, ViewEncapsulation } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { setQueryDevtoolsUiMounted } from '@ethlete/query';\nimport {\n isQueryDevtoolsEnabled,\n queryDevtoolsArmedMocks,\n queryDevtoolsEntries,\n queryDevtoolsFaults,\n queryDevtoolsTokenTtls,\n} from '@ethlete/query/devtools-contract';\nimport { filter, fromEvent, tap } from 'rxjs';\nimport { QueryDevtoolsComponent } from '@ethlete/query-devtools';\nimport {\n isQueryDevtoolsShortcut,\n QueryDevtoolsToggleComponent,\n ɵwasQueryDevtoolsOpen,\n} from '@ethlete/query-devtools/toggle';\n\nlet warnedMissingProvider = false;\n\n/**\n * The query devtools behind a deferred load: renders only the floating toggle button until the panel is\n * first asked for, then downloads `<et-query-devtools>` as its own chunk and hands over. Use it instead\n * of `<et-query-devtools>` to keep the panel out of the bundle an application ships to its users.\n *\n * Without `provideQueryDevtools()` it renders nothing at all - no toggle, no shortcut, and the panel\n * chunk is never requested - so it can be left mounted in a production build.\n *\n * Everything else is identical - the same toggle, the same `Ctrl/Cmd + Alt + Q` shortcut, and a panel\n * that was open when the tab last stored its state comes back open without a click.\n *\n * @example\n * ```html\n * <et-query-devtools-lazy />\n * ```\n */\n@Component({\n selector: 'et-query-devtools-lazy',\n template: `\n @if (enabled) {\n @defer (when load()) {\n <et-query-devtools [startOpen]=\"openOnLoad()\" />\n } @placeholder {\n <et-query-devtools-toggle [tampered]=\"tampered()\" (openChange)=\"open()\" />\n } @loading {\n <et-query-devtools-toggle [tampered]=\"tampered()\" />\n } @error {\n <et-query-devtools-toggle [tampered]=\"tampered()\" (openChange)=\"reload()\" loadFailed />\n }\n }\n `,\n encapsulation: ViewEncapsulation.None,\n imports: [QueryDevtoolsComponent, QueryDevtoolsToggleComponent],\n})\nexport class QueryDevtoolsLazyComponent {\n private document = inject(DOCUMENT);\n\n /**\n * Whether `provideQueryDevtools()` is in the application. Everything else here is gated on it - the\n * stored view state read, the shortcut listener and the template - so a build that ships the shell\n * without the provider renders nothing and can never load the panel.\n */\n protected enabled = isQueryDevtoolsEnabled();\n\n /**\n * Whether the panel is wanted. Whether it was already open has to be answered before the panel exists,\n * which is why the stored view state is read here rather than asked of the panel.\n */\n protected load = signal(this.enabled && ɵwasQueryDevtoolsOpen());\n\n /** A restored panel opens because it was open; one that was clicked open has to be told to. */\n protected openOnLoad = signal(false);\n\n /**\n * Whether anything armed is changing what the app does, for the dot on the closed toggle. The panel's\n * own badge is per-query and finer-grained; this covers what can already be armed before the panel has\n * ever been loaded - overrides and mocks restored from a previous page load, and anything an app or a\n * test armed through the API.\n */\n protected tampered = computed(\n () =>\n Object.keys(queryDevtoolsFaults()).length > 0 ||\n Object.keys(queryDevtoolsTokenTtls()).length > 0 ||\n queryDevtoolsArmedMocks().size > 0 ||\n queryDevtoolsEntries().some((entry) => (entry.overrides?.list().length ?? 0) > 0),\n );\n\n constructor() {\n if (!this.enabled) {\n if (ngDevMode && !warnedMissingProvider) {\n warnedMissingProvider = true;\n console.warn(\n \"<et-query-devtools-lazy>: provideQueryDevtools() is not in the application providers, so the devtools render nothing. Add it to bootstrapApplication's providers.\",\n );\n }\n\n return;\n }\n\n setQueryDevtoolsUiMounted(true);\n inject(DestroyRef).onDestroy(() => setQueryDevtoolsUiMounted(false));\n\n // The same shortcut the panel installs, for the one press that has to happen before it exists. Once\n // the panel is loaded it owns the key, so this stops at the first press it handles.\n fromEvent<KeyboardEvent>(this.document, 'keydown')\n .pipe(\n filter(() => !this.load()),\n filter(isQueryDevtoolsShortcut),\n tap((e) => {\n e.preventDefault();\n this.open();\n }),\n takeUntilDestroyed(),\n )\n .subscribe();\n }\n\n protected open() {\n this.openOnLoad.set(true);\n this.load.set(true);\n }\n\n /** Angular never retries a failed `@defer`, so only a page load can fetch the panel chunk again. */\n protected reload() {\n this.document.defaultView?.location.reload();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["ɵwasQueryDevtoolsOpen"],"mappings":"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"}
1
+ {"version":3,"file":"ethlete-query-devtools-lazy.mjs","names":[],"sources":["../../../../libs/query-devtools/lazy/query-devtools-lazy.component.ts","../../../../libs/query-devtools/lazy/mount-query-devtools.ts"],"sourcesContent":["import { DOCUMENT } from '@angular/common';\nimport { Component, computed, DestroyRef, inject, signal, ViewEncapsulation } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { setQueryDevtoolsUiMounted } from '@ethlete/query';\nimport {\n isQueryDevtoolsEnabled,\n isQueryDevtoolsHiddenInAutomation,\n queryDevtoolsArmedMocks,\n queryDevtoolsEntries,\n queryDevtoolsFaults,\n queryDevtoolsTokenTtls,\n} from '@ethlete/query/devtools-contract';\nimport { filter, fromEvent, tap } from 'rxjs';\nimport { QueryDevtoolsComponent } from '@ethlete/query-devtools';\nimport {\n isQueryDevtoolsShortcut,\n QueryDevtoolsToggleComponent,\n ɵwasQueryDevtoolsOpen,\n} from '@ethlete/query-devtools/toggle';\n\nlet warnedMissingProvider = false;\n\n/**\n * The query devtools behind a deferred load: renders only the floating toggle button until the panel is\n * first asked for, then downloads `<et-query-devtools>` as its own chunk and hands over. Use it instead\n * of `<et-query-devtools>` to keep the panel out of the bundle an application ships to its users.\n *\n * Without `provideQueryDevtools()` it renders nothing at all - no toggle, no shortcut, and the panel\n * chunk is never requested - so it can be left mounted in a production build. It also renders nothing in\n * a browser driven by automation (`navigator.webdriver`) unless `provideQueryDevtools({ showInAutomation: true })`.\n *\n * Everything else is identical - the same toggle, the same `Ctrl/Cmd + Alt + Q` shortcut, and a panel\n * that was open when the tab last stored its state comes back open without a click.\n *\n * @example\n * ```html\n * <et-query-devtools-lazy />\n * ```\n */\n@Component({\n selector: 'et-query-devtools-lazy',\n template: `\n @if (enabled) {\n @defer (when load()) {\n <et-query-devtools [startOpen]=\"openOnLoad()\" />\n } @placeholder {\n <et-query-devtools-toggle [tampered]=\"tampered()\" (openChange)=\"open()\" />\n } @loading {\n <et-query-devtools-toggle [tampered]=\"tampered()\" />\n } @error {\n <et-query-devtools-toggle [tampered]=\"tampered()\" (openChange)=\"reload()\" loadFailed />\n }\n }\n `,\n encapsulation: ViewEncapsulation.None,\n imports: [QueryDevtoolsComponent, QueryDevtoolsToggleComponent],\n})\nexport class QueryDevtoolsLazyComponent {\n private document = inject(DOCUMENT);\n\n /**\n * Whether `provideQueryDevtools()` is in the application. Everything else here is gated on it - the\n * stored view state read, the shortcut listener and the template - so a build that ships the shell\n * without the provider renders nothing and can never load the panel.\n */\n protected enabled = isQueryDevtoolsEnabled() && !isQueryDevtoolsHiddenInAutomation();\n\n /**\n * Whether the panel is wanted. Whether it was already open has to be answered before the panel exists,\n * which is why the stored view state is read here rather than asked of the panel.\n */\n protected load = signal(this.enabled && ɵwasQueryDevtoolsOpen());\n\n /** A restored panel opens because it was open; one that was clicked open has to be told to. */\n protected openOnLoad = signal(false);\n\n /**\n * Whether anything armed is changing what the app does, for the dot on the closed toggle. The panel's\n * own badge is per-query and finer-grained; this covers what can already be armed before the panel has\n * ever been loaded - overrides and mocks restored from a previous page load, and anything an app or a\n * test armed through the API.\n */\n protected tampered = computed(\n () =>\n Object.keys(queryDevtoolsFaults()).length > 0 ||\n Object.keys(queryDevtoolsTokenTtls()).length > 0 ||\n queryDevtoolsArmedMocks().size > 0 ||\n queryDevtoolsEntries().some((entry) => (entry.overrides?.list().length ?? 0) > 0),\n );\n\n constructor() {\n if (!this.enabled) {\n if (ngDevMode && !warnedMissingProvider && !isQueryDevtoolsEnabled()) {\n warnedMissingProvider = true;\n console.warn(\n \"<et-query-devtools-lazy>: provideQueryDevtools() is not in the application providers, so the devtools render nothing. Add it to bootstrapApplication's providers.\",\n );\n }\n\n return;\n }\n\n setQueryDevtoolsUiMounted(true);\n inject(DestroyRef).onDestroy(() => setQueryDevtoolsUiMounted(false));\n\n // The same shortcut the panel installs, for the one press that has to happen before it exists. Once\n // the panel is loaded it owns the key, so this stops at the first press it handles.\n fromEvent<KeyboardEvent>(this.document, 'keydown')\n .pipe(\n filter(() => !this.load()),\n filter(isQueryDevtoolsShortcut),\n tap((e) => {\n e.preventDefault();\n this.open();\n }),\n takeUntilDestroyed(),\n )\n .subscribe();\n }\n\n protected open() {\n this.openOnLoad.set(true);\n this.load.set(true);\n }\n\n /** Angular never retries a failed `@defer`, so only a page load can fetch the panel chunk again. */\n protected reload() {\n this.document.defaultView?.location.reload();\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport { ApplicationRef, createComponent, DestroyRef, EnvironmentInjector, RendererFactory2 } from '@angular/core';\nimport { QueryDevtoolsLazyComponent } from './query-devtools-lazy.component';\n\n/**\n * Mounts `<et-query-devtools-lazy>` on the document body and destroys it with the injector. Called by\n * `provideQueryDevtools()`; call it yourself only to mount the devtools outside a template.\n */\nexport const mountQueryDevtools = (injector: EnvironmentInjector) => {\n const host = injector.get(ApplicationRef);\n const renderer = injector.get(RendererFactory2).createRenderer(null, null);\n const element = renderer.createElement('et-query-devtools-lazy');\n\n renderer.appendChild(injector.get(DOCUMENT).body, element);\n\n const ref = createComponent(QueryDevtoolsLazyComponent, { environmentInjector: injector, hostElement: element });\n\n host.attachView(ref.hostView);\n injector.get(DestroyRef).onDestroy(() => ref.destroy());\n\n return ref;\n};\n"],"mappings":";;;;;;;;AAoBA,IAAI,wBAAwB;AAqC5B,IAAa,6BAAb,MAAa,2BAA0B;CAiCrC,cAAA;EAhCQ,KAAA,WAAW,OAAO,QAAQ;EAOxB,KAAA,UAAU,uBAAsB,KAAM,CAAC,kCAAiC;EAMxE,KAAA,OAAO,OAAO,KAAK,WAAW,sBAAqB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;EAGtD,KAAA,aAAa,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAQ1B,KAAA,WAAW,eAEjB,OAAO,KAAK,oBAAmB,CAAE,CAAC,CAAC,SAAS,KAC5C,OAAO,KAAK,uBAAsB,CAAE,CAAC,CAAC,SAAS,KAC/C,wBAAuB,CAAE,CAAC,OAAO,KACjC,qBAAoB,CAAE,CAAC,MAAM,WAAW,MAAM,WAAW,KAAI,CAAE,CAAC,UAAU,KAAK,CAAC,GACnF,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;EAGC,IAAI,CAAC,KAAK,SAAS;GACjB,IAAI,aAAa,CAAC,yBAAyB,CAAC,uBAAsB,GAAI;IACpE,wBAAwB;IACxB,QAAQ,KACN,mKAAmK;GAEvK;GAEA;EACF;EAEA,0BAA0B,IAAI;EAC9B,OAAO,UAAU,CAAC,CAAC,gBAAgB,0BAA0B,KAAK,CAAC;EAInE,UAAyB,KAAK,UAAU,SAAS,CAAC,CAC/C,KACC,aAAa,CAAC,KAAK,KAAI,CAAE,GACzB,OAAO,uBAAuB,GAC9B,KAAK,MAAK;GACR,EAAE,eAAc;GAChB,KAAK,KAAI;EACX,CAAC,GACD,mBAAkB,CAAE,CACrB,CACA,UAAS;CACd;CAEU,OAAI;EACZ,KAAK,WAAW,IAAI,IAAI;EACxB,KAAK,KAAK,IAAI,IAAI;CACpB;CAGU,SAAM;EACd,KAAK,SAAS,aAAa,SAAS,OAAM;CAC5C;CAvEW;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAA0B,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAA1B;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAA0B,cAAA;GAAA,UAAA;GAAA,UAAA;GAAA,UAhB3B;;;;;;;;;;;;;GAYT,UAAA;GAAA,cAAA,CAAA;IAAA,MAAA;IAAA,MAEiC;IAA4B,UAAA;IAAA,QAAA,CAAA,YAAA,YAAA;IAAA,SAAA,CAAA,YAAA;GAAA,CAAA;GAAA,eAAA,GAAA,kBAAA;GAAA,wBAAA,OAAA,C;;;;AAEnD,GAAA,8BAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA0B,2BAAA,C;;;GAlBtC,MAAA;GAAU,MAAA,CAAA;IACT,UAAU;IACV,UAAU;;;;;;;;;;;;;IAaV,eAAe,kBAAkB;IACjC,SAAS,CAAC,wBAAwB,4BAA4B;GAC/D,CAAA;;;;;;AChDD,MAAa,sBAAsB,aAAiC;CAClE,MAAM,OAAO,SAAS,IAAI,cAAc;CACxC,MAAM,WAAW,SAAS,IAAI,gBAAgB,CAAC,CAAC,eAAe,MAAM,IAAI;CACzE,MAAM,UAAU,SAAS,cAAc,wBAAwB;CAE/D,SAAS,YAAY,SAAS,IAAI,QAAQ,CAAC,CAAC,MAAM,OAAO;CAEzD,MAAM,MAAM,gBAAgB,4BAA4B;EAAE,qBAAqB;EAAU,aAAa;CAAO,CAAE;CAE/G,KAAK,WAAW,IAAI,QAAQ;CAC5B,SAAS,IAAI,UAAU,CAAC,CAAC,gBAAgB,IAAI,QAAO,CAAE;CAEtD,OAAO;AACT"}
@@ -1,51 +1,67 @@
1
- import { detectKbdPlatform } from '@ethlete/components';
2
- import * as i0 from '@angular/core';
3
- import { input, booleanAttribute, output, viewChild, ViewEncapsulation, Component } from '@angular/core';
4
- import { readQueryDevtoolsStore, queryDevtoolsSettings } from '@ethlete/query/devtools-contract';
5
-
6
- /**
7
- * The global devtools toggle shortcut, rendered for the current platform (`⌘⌥Q` on Apple, where the
8
- * symbols are the convention, `Ctrl+Alt+Q` everywhere else). Shown on both the floating toggle and
9
- * the panel's close button so the shortcut is discoverable without reading the docs.
10
- */
11
- const queryDevtoolsShortcutLabel = () => (detectKbdPlatform() === 'apple' ? '⌘⌥Q' : 'Ctrl+Alt+Q');
12
- /**
13
- * Whether a `keydown` is the devtools toggle shortcut (`Ctrl/Cmd + Alt + Q`). AltGr is rejected: Windows
14
- * reports it as Ctrl+Alt, and AltGr+Q types `@` on a German layout. Auto-repeat is rejected so a held
15
- * shortcut toggles once.
16
- */
17
- const isQueryDevtoolsShortcut = (e) => !e.repeat &&
18
- (e.ctrlKey || e.metaKey) &&
19
- e.altKey &&
20
- !e.getModifierState('AltGraph') &&
21
- (e.code === 'KeyQ' || e.key.toLowerCase() === 'q');
22
-
23
- /**
24
- * The floating toggle button for the query devtools. Rendered with `ShadowDom` encapsulation so the
25
- * host application's global CSS (Tailwind resets, button styles, …) can never touch it and its own
26
- * styles can never leak out. Uses px (not rem) internally so it doesn't depend on the host's root
27
- * font-size; theme accent colour is read from an inherited custom property with a fallback.
28
- *
29
- * Mounted on its own - without `<et-query-devtools-lazy>` or `<et-query-devtools>` - it declares no
30
- * devtools UI, so the floating API env and session pills take themselves off the page once the
31
- * application settles. Call `setQueryDevtoolsUiMounted(true)` to keep them.
32
- */
33
- class QueryDevtoolsToggleComponent {
34
- constructor() {
35
- this.tampered = input(false, /* @ts-ignore */
36
- ...(ngDevMode ? [{ debugName: "tampered" }] : /* istanbul ignore next */ []));
37
- this.loadFailed = input(false, { ...(ngDevMode ? { debugName: "loadFailed" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
38
- this.openChange = output();
39
- this.button = viewChild.required('button', /* @ts-ignore */
40
- ...(ngDevMode ? [{ debugName: "button" }] : /* istanbul ignore next */ []));
41
- this.shortcut = queryDevtoolsShortcutLabel();
42
- }
43
- /** Moves keyboard focus to the toggle button. */
44
- focus() {
45
- this.button().nativeElement.focus();
46
- }
47
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: QueryDevtoolsToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
48
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: QueryDevtoolsToggleComponent, isStandalone: true, selector: "et-query-devtools-toggle", inputs: { tampered: { classPropertyName: "tampered", publicName: "tampered", isSignal: true, isRequired: false, transformFunction: null }, loadFailed: { classPropertyName: "loadFailed", publicName: "loadFailed", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openChange: "openChange" }, host: { attributes: { "data-et-overlay-layer": "2147483010" } }, viewQueries: [{ propertyName: "button", first: true, predicate: ["button"], descendants: true, isSignal: true }], ngImport: i0, template: `
1
+ import * as i0 from "@angular/core";
2
+ import { Component, ViewEncapsulation, booleanAttribute, input, output, viewChild } from "@angular/core";
3
+ import { queryDevtoolsSettings, readQueryDevtoolsStore } from "@ethlete/query/devtools-contract";
4
+ const isApplePlatform = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent);
5
+ const queryDevtoolsShortcutLabel = () => isApplePlatform() ? "⌘⌥Q" : "Ctrl+Alt+Q";
6
+ const isQueryDevtoolsShortcut = (e) => !e.repeat && (e.ctrlKey || e.metaKey) && e.altKey && !e.getModifierState("AltGraph") && (e.code === "KeyQ" || e.key.toLowerCase() === "q");
7
+ var QueryDevtoolsToggleComponent = class QueryDevtoolsToggleComponent {
8
+ constructor() {
9
+ this.tampered = input(false, ...ngDevMode ? [{ debugName: "tampered" }] : /* istanbul ignore next */ []);
10
+ this.loadFailed = input(false, {
11
+ ...ngDevMode ? { debugName: "loadFailed" } : /* istanbul ignore next */ {},
12
+ transform: booleanAttribute
13
+ });
14
+ this.openChange = output();
15
+ this.button = viewChild.required("button", ...ngDevMode ? [{ debugName: "button" }] : /* istanbul ignore next */ []);
16
+ this.shortcut = queryDevtoolsShortcutLabel();
17
+ }
18
+ focus() {
19
+ this.button().nativeElement.focus();
20
+ }
21
+ static {
22
+ this.ɵfac = i0.ɵɵngDeclareFactory({
23
+ minVersion: "12.0.0",
24
+ version: "22.2.3",
25
+ ngImport: i0,
26
+ type: QueryDevtoolsToggleComponent,
27
+ deps: [],
28
+ target: i0.ɵɵFactoryTarget.Component
29
+ });
30
+ }
31
+ static {
32
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
33
+ minVersion: "17.0.0",
34
+ version: "22.2.3",
35
+ type: QueryDevtoolsToggleComponent,
36
+ isStandalone: true,
37
+ selector: "et-query-devtools-toggle",
38
+ inputs: {
39
+ tampered: {
40
+ classPropertyName: "tampered",
41
+ publicName: "tampered",
42
+ isSignal: true,
43
+ isRequired: false,
44
+ transformFunction: null
45
+ },
46
+ loadFailed: {
47
+ classPropertyName: "loadFailed",
48
+ publicName: "loadFailed",
49
+ isSignal: true,
50
+ isRequired: false,
51
+ transformFunction: null
52
+ }
53
+ },
54
+ outputs: { openChange: "openChange" },
55
+ host: { attributes: { "data-et-overlay-layer": "2147483010" } },
56
+ viewQueries: [{
57
+ propertyName: "button",
58
+ first: true,
59
+ predicate: ["button"],
60
+ descendants: true,
61
+ isSignal: true
62
+ }],
63
+ ngImport: i0,
64
+ template: `
49
65
  <button
50
66
  #button
51
67
  [title]="
@@ -68,11 +84,23 @@ class QueryDevtoolsToggleComponent {
68
84
  <span class="tamper-dot" title="A query is showing an armed override or a devtools fault"></span>
69
85
  }
70
86
  </button>
71
- `, isInline: true, styles: [":host{position:fixed;inset-block-end:16px;inset-inline-end:16px;z-index:2147483010}button{--_accent: var(--et-theme-color-primary-solid, #60a5fa);position:relative;display:inline-flex;align-items:center;gap:8px;padding:10px 12px 10px 14px;border:none;border-radius:999px;background:linear-gradient(135deg,#1f1f23,#2a2a30);color:#fafafa;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;font-weight:600;letter-spacing:.02em;cursor:pointer;box-shadow:0 6px 20px #00000059,inset 0 0 0 1px #ffffff14;transition:transform .15s ease,box-shadow .2s ease}button:before{content:\"\";position:absolute;inset:0;border-radius:inherit;padding:1px;background:linear-gradient(135deg,var(--_accent),transparent 60%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.7;transition:opacity .2s ease}button.failed{--_accent: #f87171}button:hover{transform:translateY(-2px);box-shadow:0 10px 28px #0006,0 0 0 4px color-mix(in srgb,var(--_accent) 22%,transparent),inset 0 0 0 1px #ffffff1a}button:hover:before{opacity:1}svg{inline-size:16px;block-size:16px;fill:none;stroke:var(--_accent);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.label{line-height:1}kbd{padding:3px 6px;border-radius:5px;background:#ffffff12;box-shadow:inset 0 0 0 1px #ffffff1f;color:#d4d4d8;font:inherit;font-size:11px;font-weight:500;line-height:1;white-space:nowrap}.tamper-dot{position:absolute;inset-block-start:-3px;inset-inline-end:-3px;inline-size:10px;block-size:10px;border-radius:50%;background:#f87171;box-shadow:0 0 0 2px #1f1f23}\n"], encapsulation: i0.ViewEncapsulation.ShadowDom }); }
72
- }
73
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: QueryDevtoolsToggleComponent, decorators: [{
74
- type: Component,
75
- args: [{ selector: 'et-query-devtools-toggle', template: `
87
+ `,
88
+ isInline: true,
89
+ styles: [":host{position:fixed;inset-block-end:16px;inset-inline-end:16px;z-index:2147483010}button{--_accent: var(--et-theme-color-primary-solid, #60a5fa);position:relative;display:inline-flex;align-items:center;gap:8px;padding:10px 12px 10px 14px;border:none;border-radius:999px;background:linear-gradient(135deg,#1f1f23,#2a2a30);color:#fafafa;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;font-weight:600;letter-spacing:.02em;cursor:pointer;box-shadow:0 6px 20px #00000059,inset 0 0 0 1px #ffffff14;transition:transform .15s ease,box-shadow .2s ease}button:before{content:\"\";position:absolute;inset:0;border-radius:inherit;padding:1px;background:linear-gradient(135deg,var(--_accent),transparent 60%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.7;transition:opacity .2s ease}button.failed{--_accent: #f87171}button:hover{transform:translateY(-2px);box-shadow:0 10px 28px #0006,0 0 0 4px color-mix(in srgb,var(--_accent) 22%,transparent),inset 0 0 0 1px #ffffff1a}button:hover:before{opacity:1}svg{inline-size:16px;block-size:16px;fill:none;stroke:var(--_accent);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.label{line-height:1}kbd{padding:3px 6px;border-radius:5px;background:#ffffff12;box-shadow:inset 0 0 0 1px #ffffff1f;color:#d4d4d8;font:inherit;font-size:11px;font-weight:500;line-height:1;white-space:nowrap}.tamper-dot{position:absolute;inset-block-start:-3px;inset-inline-end:-3px;inline-size:10px;block-size:10px;border-radius:50%;background:#f87171;box-shadow:0 0 0 2px #1f1f23}\n"],
90
+ encapsulation: i0.ViewEncapsulation.ShadowDom
91
+ });
92
+ }
93
+ };
94
+ i0.ɵɵngDeclareClassMetadata({
95
+ minVersion: "12.0.0",
96
+ version: "22.2.3",
97
+ ngImport: i0,
98
+ type: QueryDevtoolsToggleComponent,
99
+ decorators: [{
100
+ type: Component,
101
+ args: [{
102
+ selector: "et-query-devtools-toggle",
103
+ template: `
76
104
  <button
77
105
  #button
78
106
  [title]="
@@ -95,29 +123,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
95
123
  <span class="tamper-dot" title="A query is showing an armed override or a devtools fault"></span>
96
124
  }
97
125
  </button>
98
- `, encapsulation: ViewEncapsulation.ShadowDom, host: {
99
- // The level this button paints at - the same number as the `z-index` below; keep the two in step.
100
- // It tells @ethlete/core that a press here lands on a surface above an application overlay, so
101
- // opening the devtools does not read as an outside press and close it.
102
- 'data-et-overlay-layer': '2147483010',
103
- }, styles: [":host{position:fixed;inset-block-end:16px;inset-inline-end:16px;z-index:2147483010}button{--_accent: var(--et-theme-color-primary-solid, #60a5fa);position:relative;display:inline-flex;align-items:center;gap:8px;padding:10px 12px 10px 14px;border:none;border-radius:999px;background:linear-gradient(135deg,#1f1f23,#2a2a30);color:#fafafa;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;font-weight:600;letter-spacing:.02em;cursor:pointer;box-shadow:0 6px 20px #00000059,inset 0 0 0 1px #ffffff14;transition:transform .15s ease,box-shadow .2s ease}button:before{content:\"\";position:absolute;inset:0;border-radius:inherit;padding:1px;background:linear-gradient(135deg,var(--_accent),transparent 60%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.7;transition:opacity .2s ease}button.failed{--_accent: #f87171}button:hover{transform:translateY(-2px);box-shadow:0 10px 28px #0006,0 0 0 4px color-mix(in srgb,var(--_accent) 22%,transparent),inset 0 0 0 1px #ffffff1a}button:hover:before{opacity:1}svg{inline-size:16px;block-size:16px;fill:none;stroke:var(--_accent);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.label{line-height:1}kbd{padding:3px 6px;border-radius:5px;background:#ffffff12;box-shadow:inset 0 0 0 1px #ffffff1f;color:#d4d4d8;font:inherit;font-size:11px;font-weight:500;line-height:1;white-space:nowrap}.tamper-dot{position:absolute;inset-block-start:-3px;inset-inline-end:-3px;inline-size:10px;block-size:10px;border-radius:50%;background:#f87171;box-shadow:0 0 0 2px #1f1f23}\n"] }]
104
- }], propDecorators: { tampered: [{ type: i0.Input, args: [{ isSignal: true, alias: "tampered", required: false }] }], loadFailed: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadFailed", required: false }] }], openChange: [{ type: i0.Output, args: ["openChange"] }], button: [{ type: i0.ViewChild, args: ['button', { isSignal: true }] }] } });
105
-
106
- /**
107
- * Where the panel's own view state lives - open/closed, dock, sizes, selection, filters. Bumped
108
- * whenever a shape change would make an older stored state restore into something wrong.
109
- */
110
- const QUERY_DEVTOOLS_VIEW_STATE_KEY = 'ethlete:query:devtools:v4';
111
- /**
112
- * Whether the panel was open when this tab last stored its view state. Read by
113
- * `<et-query-devtools-lazy>`, which has to load the panel before it can ask the panel anything.
114
- */
115
- const wasQueryDevtoolsOpen = () => readQueryDevtoolsStore(queryDevtoolsSettings().viewState, QUERY_DEVTOOLS_VIEW_STATE_KEY)?.open ===
116
- true;
117
-
118
- /**
119
- * Generated bundle index. Do not edit.
120
- */
121
-
126
+ `,
127
+ encapsulation: ViewEncapsulation.ShadowDom,
128
+ host: { "data-et-overlay-layer": "2147483010" },
129
+ styles: [":host{position:fixed;inset-block-end:16px;inset-inline-end:16px;z-index:2147483010}button{--_accent: var(--et-theme-color-primary-solid, #60a5fa);position:relative;display:inline-flex;align-items:center;gap:8px;padding:10px 12px 10px 14px;border:none;border-radius:999px;background:linear-gradient(135deg,#1f1f23,#2a2a30);color:#fafafa;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;font-weight:600;letter-spacing:.02em;cursor:pointer;box-shadow:0 6px 20px #00000059,inset 0 0 0 1px #ffffff14;transition:transform .15s ease,box-shadow .2s ease}button:before{content:\"\";position:absolute;inset:0;border-radius:inherit;padding:1px;background:linear-gradient(135deg,var(--_accent),transparent 60%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.7;transition:opacity .2s ease}button.failed{--_accent: #f87171}button:hover{transform:translateY(-2px);box-shadow:0 10px 28px #0006,0 0 0 4px color-mix(in srgb,var(--_accent) 22%,transparent),inset 0 0 0 1px #ffffff1a}button:hover:before{opacity:1}svg{inline-size:16px;block-size:16px;fill:none;stroke:var(--_accent);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}.label{line-height:1}kbd{padding:3px 6px;border-radius:5px;background:#ffffff12;box-shadow:inset 0 0 0 1px #ffffff1f;color:#d4d4d8;font:inherit;font-size:11px;font-weight:500;line-height:1;white-space:nowrap}.tamper-dot{position:absolute;inset-block-start:-3px;inset-inline-end:-3px;inline-size:10px;block-size:10px;border-radius:50%;background:#f87171;box-shadow:0 0 0 2px #1f1f23}\n"]
130
+ }]
131
+ }],
132
+ propDecorators: {
133
+ tampered: [{
134
+ type: i0.Input,
135
+ args: [{
136
+ isSignal: true,
137
+ alias: "tampered",
138
+ required: false
139
+ }]
140
+ }],
141
+ loadFailed: [{
142
+ type: i0.Input,
143
+ args: [{
144
+ isSignal: true,
145
+ alias: "loadFailed",
146
+ required: false
147
+ }]
148
+ }],
149
+ openChange: [{
150
+ type: i0.Output,
151
+ args: ["openChange"]
152
+ }],
153
+ button: [{
154
+ type: i0.ViewChild,
155
+ args: ["button", { isSignal: true }]
156
+ }]
157
+ }
158
+ });
159
+ const QUERY_DEVTOOLS_VIEW_STATE_KEY = "ethlete:query:devtools:v4";
160
+ const wasQueryDevtoolsOpen = () => readQueryDevtoolsStore(queryDevtoolsSettings().viewState, QUERY_DEVTOOLS_VIEW_STATE_KEY)?.open === true;
122
161
  export { QueryDevtoolsToggleComponent, isQueryDevtoolsShortcut, queryDevtoolsShortcutLabel, QUERY_DEVTOOLS_VIEW_STATE_KEY as ɵQUERY_DEVTOOLS_VIEW_STATE_KEY, wasQueryDevtoolsOpen as ɵwasQueryDevtoolsOpen };
123
- //# sourceMappingURL=ethlete-query-devtools-toggle.mjs.map
162
+
163
+ //# sourceMappingURL=ethlete-query-devtools-toggle.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ethlete-query-devtools-toggle.mjs","sources":["../../../../libs/query-devtools/toggle/query-devtools-shortcut.ts","../../../../libs/query-devtools/toggle/query-devtools-toggle.component.ts","../../../../libs/query-devtools/toggle/query-devtools-view-state.ts","../../../../libs/query-devtools/toggle/ethlete-query-devtools-toggle.ts"],"sourcesContent":["import { detectKbdPlatform } from '@ethlete/components';\n\n/**\n * The global devtools toggle shortcut, rendered for the current platform (`⌘⌥Q` on Apple, where the\n * symbols are the convention, `Ctrl+Alt+Q` everywhere else). Shown on both the floating toggle and\n * the panel's close button so the shortcut is discoverable without reading the docs.\n */\nexport const queryDevtoolsShortcutLabel = () => (detectKbdPlatform() === 'apple' ? '⌘⌥Q' : 'Ctrl+Alt+Q');\n\n/**\n * Whether a `keydown` is the devtools toggle shortcut (`Ctrl/Cmd + Alt + Q`). AltGr is rejected: Windows\n * reports it as Ctrl+Alt, and AltGr+Q types `@` on a German layout. Auto-repeat is rejected so a held\n * shortcut toggles once.\n */\nexport const isQueryDevtoolsShortcut = (e: KeyboardEvent) =>\n !e.repeat &&\n (e.ctrlKey || e.metaKey) &&\n e.altKey &&\n !e.getModifierState('AltGraph') &&\n (e.code === 'KeyQ' || e.key.toLowerCase() === 'q');\n","import { booleanAttribute, Component, ElementRef, input, output, viewChild, ViewEncapsulation } from '@angular/core';\nimport { queryDevtoolsShortcutLabel } from './query-devtools-shortcut';\n\n/**\n * The floating toggle button for the query devtools. Rendered with `ShadowDom` encapsulation so the\n * host application's global CSS (Tailwind resets, button styles, …) can never touch it and its own\n * styles can never leak out. Uses px (not rem) internally so it doesn't depend on the host's root\n * font-size; theme accent colour is read from an inherited custom property with a fallback.\n *\n * Mounted on its own - without `<et-query-devtools-lazy>` or `<et-query-devtools>` - it declares no\n * devtools UI, so the floating API env and session pills take themselves off the page once the\n * application settles. Call `setQueryDevtoolsUiMounted(true)` to keep them.\n */\n@Component({\n selector: 'et-query-devtools-toggle',\n template: `\n <button\n #button\n [title]=\"\n loadFailed()\n ? 'The devtools panel failed to load. Click to reload the page.'\n : 'Open query devtools (' + shortcut + ')'\n \"\n [class.failed]=\"loadFailed()\"\n (click)=\"openChange.emit()\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <ellipse cx=\"12\" cy=\"6\" rx=\"7.5\" ry=\"3\" />\n <path d=\"M4.5 6v6c0 1.66 3.36 3 7.5 3s7.5-1.34 7.5-3V6\" />\n <path d=\"M4.5 12v6c0 1.66 3.36 3 7.5 3s7.5-1.34 7.5-3v-6\" />\n </svg>\n <span class=\"label\">Query</span>\n <kbd>{{ shortcut }}</kbd>\n @if (tampered()) {\n <span class=\"tamper-dot\" title=\"A query is showing an armed override or a devtools fault\"></span>\n }\n </button>\n `,\n // Shadow DOM is intentional: this always-visible floating button must be fully isolated from the\n // host app's global CSS (resets, Tailwind, button styles), which the rest of the panel can't be.\n // eslint-disable-next-line ethlete/require-view-encapsulation-none\n encapsulation: ViewEncapsulation.ShadowDom,\n host: {\n // The level this button paints at - the same number as the `z-index` below; keep the two in step.\n // It tells @ethlete/core that a press here lands on a surface above an application overlay, so\n // opening the devtools does not read as an outside press and close it.\n 'data-et-overlay-layer': '2147483010',\n },\n styles: `\n :host {\n position: fixed;\n inset-block-end: 16px;\n inset-inline-end: 16px;\n /* Above DEFAULT_OVERLAY_LAYER (2147483003) in @ethlete/core: rendered by the lazy shell, the\n button is a sibling of the application's content, so anything less puts an open modal over it. */\n z-index: 2147483010;\n }\n\n button {\n --_accent: var(--et-theme-color-primary-solid, #60a5fa);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px 10px 14px;\n border: none;\n border-radius: 999px;\n background: linear-gradient(135deg, #1f1f23, #2a2a30);\n color: #fafafa;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.02em;\n cursor: pointer;\n box-shadow:\n 0 6px 20px rgb(0 0 0 / 0.35),\n inset 0 0 0 1px rgb(255 255 255 / 0.08);\n transition:\n transform 0.15s ease,\n box-shadow 0.2s ease;\n }\n\n /* Gradient accent ring via a masked pseudo-element. */\n button::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n padding: 1px;\n background: linear-gradient(135deg, var(--_accent), transparent 60%);\n -webkit-mask:\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n opacity: 0.7;\n transition: opacity 0.2s ease;\n }\n\n button.failed {\n --_accent: #f87171;\n }\n\n button:hover {\n transform: translateY(-2px);\n box-shadow:\n 0 10px 28px rgb(0 0 0 / 0.4),\n 0 0 0 4px color-mix(in srgb, var(--_accent) 22%, transparent),\n inset 0 0 0 1px rgb(255 255 255 / 0.1);\n }\n\n button:hover::before {\n opacity: 1;\n }\n\n svg {\n inline-size: 16px;\n block-size: 16px;\n fill: none;\n stroke: var(--_accent);\n stroke-width: 1.6;\n stroke-linecap: round;\n stroke-linejoin: round;\n }\n\n .label {\n line-height: 1;\n }\n\n kbd {\n padding: 3px 6px;\n border-radius: 5px;\n background: rgb(255 255 255 / 0.07);\n box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12);\n color: #d4d4d8;\n font: inherit;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n /* The Apple glyphs need no separator; the \"Ctrl+Alt+Q\" spelling is wider, hence the nowrap. */\n white-space: nowrap;\n }\n\n /* Visible with the panel closed, which is the point - a query being tampered with is a fact about\n the running app, not just about whatever the panel happens to have open. */\n .tamper-dot {\n position: absolute;\n inset-block-start: -3px;\n inset-inline-end: -3px;\n inline-size: 10px;\n block-size: 10px;\n border-radius: 50%;\n background: #f87171;\n box-shadow: 0 0 0 2px #1f1f23;\n }\n `,\n})\nexport class QueryDevtoolsToggleComponent {\n public tampered = input(false);\n public loadFailed = input(false, { transform: booleanAttribute });\n public openChange = output<void>();\n\n private button = viewChild.required<ElementRef<HTMLButtonElement>>('button');\n\n protected shortcut = queryDevtoolsShortcutLabel();\n\n /** Moves keyboard focus to the toggle button. */\n public focus() {\n this.button().nativeElement.focus();\n }\n}\n","import { queryDevtoolsSettings, readQueryDevtoolsStore } from '@ethlete/query/devtools-contract';\n\n/**\n * Where the panel's own view state lives - open/closed, dock, sizes, selection, filters. Bumped\n * whenever a shape change would make an older stored state restore into something wrong.\n */\nexport const QUERY_DEVTOOLS_VIEW_STATE_KEY = 'ethlete:query:devtools:v4';\n\n/**\n * Whether the panel was open when this tab last stored its view state. Read by\n * `<et-query-devtools-lazy>`, which has to load the panel before it can ask the panel anything.\n */\nexport const wasQueryDevtoolsOpen = () =>\n readQueryDevtoolsStore<{ open?: boolean }>(queryDevtoolsSettings().viewState, QUERY_DEVTOOLS_VIEW_STATE_KEY)?.open ===\n true;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ethlete-query-devtools-toggle.mjs","names":[],"sources":["../../../../libs/query-devtools/toggle/query-devtools-shortcut.ts","../../../../libs/query-devtools/toggle/query-devtools-toggle.component.ts","../../../../libs/query-devtools/toggle/query-devtools-view-state.ts"],"sourcesContent":["const isApplePlatform = () =>\n typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent);\n\n/**\n * The global devtools toggle shortcut, rendered for the current platform (`⌘⌥Q` on Apple, where the\n * symbols are the convention, `Ctrl+Alt+Q` everywhere else). Shown on both the floating toggle and\n * the panel's close button so the shortcut is discoverable without reading the docs.\n */\nexport const queryDevtoolsShortcutLabel = () => (isApplePlatform() ? '⌘⌥Q' : 'Ctrl+Alt+Q');\n\n/**\n * Whether a `keydown` is the devtools toggle shortcut (`Ctrl/Cmd + Alt + Q`). AltGr is rejected: Windows\n * reports it as Ctrl+Alt, and AltGr+Q types `@` on a German layout. Auto-repeat is rejected so a held\n * shortcut toggles once.\n */\nexport const isQueryDevtoolsShortcut = (e: KeyboardEvent) =>\n !e.repeat &&\n (e.ctrlKey || e.metaKey) &&\n e.altKey &&\n !e.getModifierState('AltGraph') &&\n (e.code === 'KeyQ' || e.key.toLowerCase() === 'q');\n","import { booleanAttribute, Component, ElementRef, input, output, viewChild, ViewEncapsulation } from '@angular/core';\nimport { queryDevtoolsShortcutLabel } from './query-devtools-shortcut';\n\n/**\n * The floating toggle button for the query devtools. Rendered with `ShadowDom` encapsulation so the\n * host application's global CSS (Tailwind resets, button styles, …) can never touch it and its own\n * styles can never leak out. Uses px (not rem) internally so it doesn't depend on the host's root\n * font-size; theme accent colour is read from an inherited custom property with a fallback.\n *\n * Mounted on its own - without `<et-query-devtools-lazy>` or `<et-query-devtools>` - it declares no\n * devtools UI, so the floating API env and session pills take themselves off the page once the\n * application settles. Call `setQueryDevtoolsUiMounted(true)` to keep them.\n */\n@Component({\n selector: 'et-query-devtools-toggle',\n template: `\n <button\n #button\n [title]=\"\n loadFailed()\n ? 'The devtools panel failed to load. Click to reload the page.'\n : 'Open query devtools (' + shortcut + ')'\n \"\n [class.failed]=\"loadFailed()\"\n (click)=\"openChange.emit()\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <ellipse cx=\"12\" cy=\"6\" rx=\"7.5\" ry=\"3\" />\n <path d=\"M4.5 6v6c0 1.66 3.36 3 7.5 3s7.5-1.34 7.5-3V6\" />\n <path d=\"M4.5 12v6c0 1.66 3.36 3 7.5 3s7.5-1.34 7.5-3v-6\" />\n </svg>\n <span class=\"label\">Query</span>\n <kbd>{{ shortcut }}</kbd>\n @if (tampered()) {\n <span class=\"tamper-dot\" title=\"A query is showing an armed override or a devtools fault\"></span>\n }\n </button>\n `,\n // Shadow DOM is intentional: this always-visible floating button must be fully isolated from the\n // host app's global CSS (resets, Tailwind, button styles), which the rest of the panel can't be.\n // eslint-disable-next-line ethlete/require-view-encapsulation-none\n encapsulation: ViewEncapsulation.ShadowDom,\n host: {\n // The level this button paints at - the same number as the `z-index` below; keep the two in step.\n // It tells @ethlete/core that a press here lands on a surface above an application overlay, so\n // opening the devtools does not read as an outside press and close it.\n 'data-et-overlay-layer': '2147483010',\n },\n styles: `\n :host {\n position: fixed;\n inset-block-end: 16px;\n inset-inline-end: 16px;\n /* Above DEFAULT_OVERLAY_LAYER (2147483003) in @ethlete/core: rendered by the lazy shell, the\n button is a sibling of the application's content, so anything less puts an open modal over it. */\n z-index: 2147483010;\n }\n\n button {\n --_accent: var(--et-theme-color-primary-solid, #60a5fa);\n\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px 10px 14px;\n border: none;\n border-radius: 999px;\n background: linear-gradient(135deg, #1f1f23, #2a2a30);\n color: #fafafa;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.02em;\n cursor: pointer;\n box-shadow:\n 0 6px 20px rgb(0 0 0 / 0.35),\n inset 0 0 0 1px rgb(255 255 255 / 0.08);\n transition:\n transform 0.15s ease,\n box-shadow 0.2s ease;\n }\n\n /* Gradient accent ring via a masked pseudo-element. */\n button::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n padding: 1px;\n background: linear-gradient(135deg, var(--_accent), transparent 60%);\n -webkit-mask:\n linear-gradient(#000 0 0) content-box,\n linear-gradient(#000 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n opacity: 0.7;\n transition: opacity 0.2s ease;\n }\n\n button.failed {\n --_accent: #f87171;\n }\n\n button:hover {\n transform: translateY(-2px);\n box-shadow:\n 0 10px 28px rgb(0 0 0 / 0.4),\n 0 0 0 4px color-mix(in srgb, var(--_accent) 22%, transparent),\n inset 0 0 0 1px rgb(255 255 255 / 0.1);\n }\n\n button:hover::before {\n opacity: 1;\n }\n\n svg {\n inline-size: 16px;\n block-size: 16px;\n fill: none;\n stroke: var(--_accent);\n stroke-width: 1.6;\n stroke-linecap: round;\n stroke-linejoin: round;\n }\n\n .label {\n line-height: 1;\n }\n\n kbd {\n padding: 3px 6px;\n border-radius: 5px;\n background: rgb(255 255 255 / 0.07);\n box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12);\n color: #d4d4d8;\n font: inherit;\n font-size: 11px;\n font-weight: 500;\n line-height: 1;\n /* The Apple glyphs need no separator; the \"Ctrl+Alt+Q\" spelling is wider, hence the nowrap. */\n white-space: nowrap;\n }\n\n /* Visible with the panel closed, which is the point - a query being tampered with is a fact about\n the running app, not just about whatever the panel happens to have open. */\n .tamper-dot {\n position: absolute;\n inset-block-start: -3px;\n inset-inline-end: -3px;\n inline-size: 10px;\n block-size: 10px;\n border-radius: 50%;\n background: #f87171;\n box-shadow: 0 0 0 2px #1f1f23;\n }\n `,\n})\nexport class QueryDevtoolsToggleComponent {\n public tampered = input(false);\n public loadFailed = input(false, { transform: booleanAttribute });\n public openChange = output<void>();\n\n private button = viewChild.required<ElementRef<HTMLButtonElement>>('button');\n\n protected shortcut = queryDevtoolsShortcutLabel();\n\n /** Moves keyboard focus to the toggle button. */\n public focus() {\n this.button().nativeElement.focus();\n }\n}\n","import { queryDevtoolsSettings, readQueryDevtoolsStore } from '@ethlete/query/devtools-contract';\n\n/**\n * Where the panel's own view state lives - open/closed, dock, sizes, selection, filters. Bumped\n * whenever a shape change would make an older stored state restore into something wrong.\n */\nexport const QUERY_DEVTOOLS_VIEW_STATE_KEY = 'ethlete:query:devtools:v4';\n\n/**\n * Whether the panel was open when this tab last stored its view state. Read by\n * `<et-query-devtools-lazy>`, which has to load the panel before it can ask the panel anything.\n */\nexport const wasQueryDevtoolsOpen = () =>\n readQueryDevtoolsStore<{ open?: boolean }>(queryDevtoolsSettings().viewState, QUERY_DEVTOOLS_VIEW_STATE_KEY)?.open ===\n true;\n"],"mappings":";;;AAAA,MAAM,wBACJ,OAAO,cAAc,eAAe,wBAAwB,KAAK,UAAU,YAAY,UAAU,SAAS;AAO5G,MAAa,mCAAoC,gBAAe,IAAK,QAAQ;AAO7E,MAAa,2BAA2B,MACtC,CAAC,EAAE,WACF,EAAE,WAAW,EAAE,YAChB,EAAE,UACF,CAAC,EAAE,iBAAiB,UAAU,MAC7B,EAAE,SAAS,UAAU,EAAE,IAAI,YAAW,MAAO;AC2IhD,IAAa,+BAAb,MAAa,6BAA4B;CAlJzC,cAAA;EAmJS,KAAA,WAAW,MAAM,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;EACvB,KAAA,aAAa,MAAM,OAAK;GAAA,GAAA,YAAA,EAAA,WAAA,aAAA,+BAAA,CAAA;GAAI,WAAW;EAAgB,CAAA;EACvD,KAAA,aAAa,OAAM;EAElB,KAAA,SAAS,UAAU,SAAwC,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAElE,KAAA,WAAW,2BAA0B;CAMhD;CAHQ,QAAK;EACV,KAAK,OAAM,CAAE,CAAC,cAAc,MAAK;CACnC;CAZW;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAA4B,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAA5B;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAA4B,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,UAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,YAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,SAAA,EAAA,YAAA,aAAA;GAAA,MAAA,EAAA,YAAA,EAAA,yBAAA,aAAA,EAAA;GAAA,aAAA,CAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAAA,CAAA,QAAA;IAAA,aAAA;IAAA,UAAA;GAAA,CAAA;GAAA,UAAA;GAAA,UAhJ7B;;;;;;;;;;;;;;;;;;;;;;;;GAuBT,UAAA;GAAA,QAAA,CAAA,6lDAAA;GAAA,eAAA,GAAA,kBAAA;EAAA,CAAA;CAAA;;AAyHU,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA4B,YAAA,CAAA;EAlJxC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAA0B,UAC1B;;;;;;;;;;;;;;;;;;;;;;;;GAuBT,eAIc,kBAAkB;GAAS,MACpC,EAIJ,yBAAyB,aAC1B;GAAA,QAAA,CAAA,6lDAAA;EAAA,CAAA;CAoHkE,CAAA;CAAA,gBAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,YAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,UAAQ,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA;AC9J7E,MAAa,gCAAgC;AAM7C,MAAa,6BACX,uBAA2C,sBAAqB,CAAE,CAAC,WAAW,6BAA6B,CAAC,EAAE,SAC9G"}