@aglyn/shared-ui-jsx 1.0.0-beta.233 → 1.0.0-beta.235
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/package.json +5 -5
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/components/activity-details-dialog.component.d.ts +69 -0
- package/src/lib/components/activity-details-dialog.component.js +186 -0
- package/src/lib/components/activity-details-dialog.component.js.map +1 -0
- package/src/lib/components/app-link.d.ts +72 -8
- package/src/lib/components/app-link.js +20 -2
- package/src/lib/components/app-link.js.map +1 -1
- package/src/lib/components/list-table.component.d.ts +18 -2
- package/src/lib/components/list-table.component.js +11 -18
- package/src/lib/components/list-table.component.js.map +1 -1
- package/src/lib/components/row-actions-menu.component.d.ts +6 -1
- package/src/lib/components/row-actions-menu.component.js +15 -6
- package/src/lib/components/row-actions-menu.component.js.map +1 -1
- package/src/lib/hooks/use-viewport-fill.d.ts +31 -8
- package/src/lib/hooks/use-viewport-fill.js +83 -11
- package/src/lib/hooks/use-viewport-fill.js.map +1 -1
- package/src/lib/utils/new-tab.d.ts +82 -0
- package/src/lib/utils/new-tab.js +97 -0
- package/src/lib/utils/new-tab.js.map +1 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Preview and view links open in a NEW TAB (AGL-3660).
|
|
19
|
+
*
|
|
20
|
+
* A "Preview", "View live", "Visit site" or eye-icon action shows the reader
|
|
21
|
+
* something ELSE — a rendered artifact, a published page, a buyer's view —
|
|
22
|
+
* while they are in the middle of working on a list or an editor. Sending the
|
|
23
|
+
* console tab there threw away their place (filters, scroll, an open drawer)
|
|
24
|
+
* for a glance they meant to take beside it. So every such action opens a tab
|
|
25
|
+
* of its own, and says so to assistive tech.
|
|
26
|
+
*
|
|
27
|
+
* This module is the one place that spelling lives:
|
|
28
|
+
*
|
|
29
|
+
* - {@link newTabLinkProps} for an anchor / `AppLink` / MUI `href` control;
|
|
30
|
+
* - {@link openInNewTab} for a click handler that has the URL in hand;
|
|
31
|
+
* - {@link openPendingTab} for one that must `await` the URL first — a tab
|
|
32
|
+
* opened after the await is a popup the browser blocks;
|
|
33
|
+
* - {@link withNewTabHint} for the accessible name.
|
|
34
|
+
*
|
|
35
|
+
* `apps/console/specs/preview-links-open-in-new-tab.spec.ts` sweeps the
|
|
36
|
+
* console and plugin sources and fails when a preview/view action is wired
|
|
37
|
+
* without one of these (or an equivalent `target="_blank"`).
|
|
38
|
+
*/
|
|
39
|
+
/** The suffix every new-tab control's accessible name ends with. */
|
|
40
|
+
export declare const NEW_TAB_HINT = "(opens in a new tab)";
|
|
41
|
+
/**
|
|
42
|
+
* `noopener` so the opened page cannot script this console through
|
|
43
|
+
* `window.opener`; `noreferrer` so a published site does not learn the
|
|
44
|
+
* console URL (org slug, site id) it was opened from.
|
|
45
|
+
*/
|
|
46
|
+
export declare const NEW_TAB_REL = "noopener noreferrer";
|
|
47
|
+
/** Spread onto an anchor-rendering control: `<AppLink {...newTabLinkProps}>`. */
|
|
48
|
+
export declare const newTabLinkProps: Readonly<{
|
|
49
|
+
readonly target: "_blank";
|
|
50
|
+
readonly rel: "noopener noreferrer";
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* `rel` for a new-tab link that already carries tokens of its own
|
|
54
|
+
* (`nofollow`, say): theirs, plus `noopener noreferrer`, each once.
|
|
55
|
+
*/
|
|
56
|
+
export declare function mergeNewTabRel(rel?: string | null): string;
|
|
57
|
+
/** `label` with {@link NEW_TAB_HINT} appended, exactly once. */
|
|
58
|
+
export declare function withNewTabHint(label: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Open `url` in a new tab from a click handler. Use this rather than
|
|
61
|
+
* `router.push` / `location.assign` for a preview or view action.
|
|
62
|
+
*/
|
|
63
|
+
export declare function openInNewTab(url: string): void;
|
|
64
|
+
/** A tab opened during the click, navigated once its URL is known. */
|
|
65
|
+
export interface PendingTab {
|
|
66
|
+
/** Send the tab to `url`; falls back to {@link openInNewTab} if the browser
|
|
67
|
+
* refused the blank tab. Never navigates the console tab itself. */
|
|
68
|
+
navigate(url: string): void;
|
|
69
|
+
/** Close the blank tab, for when the URL could not be produced. */
|
|
70
|
+
close(): void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Open a blank tab NOW, inside the click's user activation, and point it at a
|
|
74
|
+
* URL that is only known after an `await`.
|
|
75
|
+
*
|
|
76
|
+
* NOT `window.open('', '_blank', 'noopener')`: with `noopener` the browser
|
|
77
|
+
* returns `null`, so there is no handle to navigate — the pattern that left
|
|
78
|
+
* "Preview on site" opening an empty tab AND moving the console tab. Instead
|
|
79
|
+
* the tab is opened with a handle and its `opener` is cut by hand before it
|
|
80
|
+
* goes anywhere, which is what `noopener` would have done.
|
|
81
|
+
*/
|
|
82
|
+
export declare function openPendingTab(): PendingTab;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* Preview and view links open in a NEW TAB (AGL-3660).
|
|
18
|
+
*
|
|
19
|
+
* A "Preview", "View live", "Visit site" or eye-icon action shows the reader
|
|
20
|
+
* something ELSE — a rendered artifact, a published page, a buyer's view —
|
|
21
|
+
* while they are in the middle of working on a list or an editor. Sending the
|
|
22
|
+
* console tab there threw away their place (filters, scroll, an open drawer)
|
|
23
|
+
* for a glance they meant to take beside it. So every such action opens a tab
|
|
24
|
+
* of its own, and says so to assistive tech.
|
|
25
|
+
*
|
|
26
|
+
* This module is the one place that spelling lives:
|
|
27
|
+
*
|
|
28
|
+
* - {@link newTabLinkProps} for an anchor / `AppLink` / MUI `href` control;
|
|
29
|
+
* - {@link openInNewTab} for a click handler that has the URL in hand;
|
|
30
|
+
* - {@link openPendingTab} for one that must `await` the URL first — a tab
|
|
31
|
+
* opened after the await is a popup the browser blocks;
|
|
32
|
+
* - {@link withNewTabHint} for the accessible name.
|
|
33
|
+
*
|
|
34
|
+
* `apps/console/specs/preview-links-open-in-new-tab.spec.ts` sweeps the
|
|
35
|
+
* console and plugin sources and fails when a preview/view action is wired
|
|
36
|
+
* without one of these (or an equivalent `target="_blank"`).
|
|
37
|
+
*/ /** The suffix every new-tab control's accessible name ends with. */ export const NEW_TAB_HINT = '(opens in a new tab)';
|
|
38
|
+
/**
|
|
39
|
+
* `noopener` so the opened page cannot script this console through
|
|
40
|
+
* `window.opener`; `noreferrer` so a published site does not learn the
|
|
41
|
+
* console URL (org slug, site id) it was opened from.
|
|
42
|
+
*/ export const NEW_TAB_REL = 'noopener noreferrer';
|
|
43
|
+
/** Spread onto an anchor-rendering control: `<AppLink {...newTabLinkProps}>`. */ export const newTabLinkProps = Object.freeze({
|
|
44
|
+
target: '_blank',
|
|
45
|
+
rel: NEW_TAB_REL
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* `rel` for a new-tab link that already carries tokens of its own
|
|
49
|
+
* (`nofollow`, say): theirs, plus `noopener noreferrer`, each once.
|
|
50
|
+
*/ export function mergeNewTabRel(rel) {
|
|
51
|
+
const tokens = new Set(`${rel != null ? rel : ''} ${NEW_TAB_REL}`.split(/\s+/).filter(Boolean));
|
|
52
|
+
return [
|
|
53
|
+
...tokens
|
|
54
|
+
].join(' ');
|
|
55
|
+
}
|
|
56
|
+
/** `label` with {@link NEW_TAB_HINT} appended, exactly once. */ export function withNewTabHint(label) {
|
|
57
|
+
const trimmed = label.trim();
|
|
58
|
+
return trimmed.endsWith(NEW_TAB_HINT) ? trimmed : `${trimmed} ${NEW_TAB_HINT}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Open `url` in a new tab from a click handler. Use this rather than
|
|
62
|
+
* `router.push` / `location.assign` for a preview or view action.
|
|
63
|
+
*/ export function openInNewTab(url) {
|
|
64
|
+
if (typeof window === 'undefined' || !url) return;
|
|
65
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Open a blank tab NOW, inside the click's user activation, and point it at a
|
|
69
|
+
* URL that is only known after an `await`.
|
|
70
|
+
*
|
|
71
|
+
* NOT `window.open('', '_blank', 'noopener')`: with `noopener` the browser
|
|
72
|
+
* returns `null`, so there is no handle to navigate — the pattern that left
|
|
73
|
+
* "Preview on site" opening an empty tab AND moving the console tab. Instead
|
|
74
|
+
* the tab is opened with a handle and its `opener` is cut by hand before it
|
|
75
|
+
* goes anywhere, which is what `noopener` would have done.
|
|
76
|
+
*/ export function openPendingTab() {
|
|
77
|
+
const tab = typeof window === 'undefined' ? null : window.open('about:blank', '_blank');
|
|
78
|
+
if (tab) {
|
|
79
|
+
try {
|
|
80
|
+
tab.opener = null;
|
|
81
|
+
} catch (unused) {
|
|
82
|
+
// Cross-origin by now is impossible for about:blank; nothing to cut.
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
navigate (url) {
|
|
87
|
+
if (!url) return;
|
|
88
|
+
if (tab && !tab.closed) tab.location.replace(url);
|
|
89
|
+
else openInNewTab(url);
|
|
90
|
+
},
|
|
91
|
+
close () {
|
|
92
|
+
if (tab && !tab.closed) tab.close();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=new-tab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/utils/new-tab.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Preview and view links open in a NEW TAB (AGL-3660).\n *\n * A \"Preview\", \"View live\", \"Visit site\" or eye-icon action shows the reader\n * something ELSE — a rendered artifact, a published page, a buyer's view —\n * while they are in the middle of working on a list or an editor. Sending the\n * console tab there threw away their place (filters, scroll, an open drawer)\n * for a glance they meant to take beside it. So every such action opens a tab\n * of its own, and says so to assistive tech.\n *\n * This module is the one place that spelling lives:\n *\n * - {@link newTabLinkProps} for an anchor / `AppLink` / MUI `href` control;\n * - {@link openInNewTab} for a click handler that has the URL in hand;\n * - {@link openPendingTab} for one that must `await` the URL first — a tab\n * opened after the await is a popup the browser blocks;\n * - {@link withNewTabHint} for the accessible name.\n *\n * `apps/console/specs/preview-links-open-in-new-tab.spec.ts` sweeps the\n * console and plugin sources and fails when a preview/view action is wired\n * without one of these (or an equivalent `target=\"_blank\"`).\n */\n\n/** The suffix every new-tab control's accessible name ends with. */\nexport const NEW_TAB_HINT = '(opens in a new tab)'\n\n/**\n * `noopener` so the opened page cannot script this console through\n * `window.opener`; `noreferrer` so a published site does not learn the\n * console URL (org slug, site id) it was opened from.\n */\nexport const NEW_TAB_REL = 'noopener noreferrer'\n\n/** Spread onto an anchor-rendering control: `<AppLink {...newTabLinkProps}>`. */\nexport const newTabLinkProps = Object.freeze({\n target: '_blank',\n rel: NEW_TAB_REL,\n} as const)\n\n/**\n * `rel` for a new-tab link that already carries tokens of its own\n * (`nofollow`, say): theirs, plus `noopener noreferrer`, each once.\n */\nexport function mergeNewTabRel(rel?: string | null): string {\n const tokens = new Set(\n `${rel ?? ''} ${NEW_TAB_REL}`.split(/\\s+/).filter(Boolean),\n )\n return [...tokens].join(' ')\n}\n\n/** `label` with {@link NEW_TAB_HINT} appended, exactly once. */\nexport function withNewTabHint(label: string): string {\n const trimmed = label.trim()\n return trimmed.endsWith(NEW_TAB_HINT) ? trimmed : `${trimmed} ${NEW_TAB_HINT}`\n}\n\n/**\n * Open `url` in a new tab from a click handler. Use this rather than\n * `router.push` / `location.assign` for a preview or view action.\n */\nexport function openInNewTab(url: string): void {\n if (typeof window === 'undefined' || !url) return\n window.open(url, '_blank', 'noopener,noreferrer')\n}\n\n/** A tab opened during the click, navigated once its URL is known. */\nexport interface PendingTab {\n /** Send the tab to `url`; falls back to {@link openInNewTab} if the browser\n * refused the blank tab. Never navigates the console tab itself. */\n navigate(url: string): void\n /** Close the blank tab, for when the URL could not be produced. */\n close(): void\n}\n\n/**\n * Open a blank tab NOW, inside the click's user activation, and point it at a\n * URL that is only known after an `await`.\n *\n * NOT `window.open('', '_blank', 'noopener')`: with `noopener` the browser\n * returns `null`, so there is no handle to navigate — the pattern that left\n * \"Preview on site\" opening an empty tab AND moving the console tab. Instead\n * the tab is opened with a handle and its `opener` is cut by hand before it\n * goes anywhere, which is what `noopener` would have done.\n */\nexport function openPendingTab(): PendingTab {\n const tab =\n typeof window === 'undefined' ? null : window.open('about:blank', '_blank')\n if (tab) {\n try {\n tab.opener = null\n } catch {\n // Cross-origin by now is impossible for about:blank; nothing to cut.\n }\n }\n return {\n navigate(url: string) {\n if (!url) return\n if (tab && !tab.closed) tab.location.replace(url)\n else openInNewTab(url)\n },\n close() {\n if (tab && !tab.closed) tab.close()\n },\n }\n}\n"],"names":["NEW_TAB_HINT","NEW_TAB_REL","newTabLinkProps","Object","freeze","target","rel","mergeNewTabRel","tokens","Set","split","filter","Boolean","join","withNewTabHint","label","trimmed","trim","endsWith","openInNewTab","url","window","open","openPendingTab","tab","opener","navigate","closed","location","replace","close"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;CAqBC,GAED,kEAAkE,GAClE,OAAO,MAAMA,eAAe,uBAAsB;AAElD;;;;CAIC,GACD,OAAO,MAAMC,cAAc,sBAAqB;AAEhD,+EAA+E,GAC/E,OAAO,MAAMC,kBAAkBC,OAAOC,MAAM,CAAC;IAC3CC,QAAQ;IACRC,KAAKL;AACP,GAAW;AAEX;;;CAGC,GACD,OAAO,SAASM,eAAeD,GAAmB;IAChD,MAAME,SAAS,IAAIC,IACjB,GAAGH,cAAAA,MAAO,GAAG,CAAC,EAAEL,aAAa,CAACS,KAAK,CAAC,OAAOC,MAAM,CAACC;IAEpD,OAAO;WAAIJ;KAAO,CAACK,IAAI,CAAC;AAC1B;AAEA,8DAA8D,GAC9D,OAAO,SAASC,eAAeC,KAAa;IAC1C,MAAMC,UAAUD,MAAME,IAAI;IAC1B,OAAOD,QAAQE,QAAQ,CAAClB,gBAAgBgB,UAAU,GAAGA,QAAQ,CAAC,EAAEhB,cAAc;AAChF;AAEA;;;CAGC,GACD,OAAO,SAASmB,aAAaC,GAAW;IACtC,IAAI,OAAOC,WAAW,eAAe,CAACD,KAAK;IAC3CC,OAAOC,IAAI,CAACF,KAAK,UAAU;AAC7B;AAWA;;;;;;;;;CASC,GACD,OAAO,SAASG;IACd,MAAMC,MACJ,OAAOH,WAAW,cAAc,OAAOA,OAAOC,IAAI,CAAC,eAAe;IACpE,IAAIE,KAAK;QACP,IAAI;YACFA,IAAIC,MAAM,GAAG;QACf,EAAE,eAAM;QACN,qEAAqE;QACvE;IACF;IACA,OAAO;QACLC,UAASN,GAAW;YAClB,IAAI,CAACA,KAAK;YACV,IAAII,OAAO,CAACA,IAAIG,MAAM,EAAEH,IAAII,QAAQ,CAACC,OAAO,CAACT;iBACxCD,aAAaC;QACpB;QACAU;YACE,IAAIN,OAAO,CAACA,IAAIG,MAAM,EAAEH,IAAIM,KAAK;QACnC;IACF;AACF"}
|