@aglyn/shared-ui-jsx 1.0.0-beta.277 → 1.0.0-beta.283
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 +6 -5
- package/src/lib/components/beta-chip.component.d.ts +27 -0
- package/src/lib/components/beta-chip.component.js +65 -0
- package/src/lib/components/beta-chip.component.js.map +1 -0
- package/src/lib/components/confirmation-provider.component.js +6 -0
- package/src/lib/components/confirmation-provider.component.js.map +1 -1
- package/src/lib/components/dialog-confirm.js +2 -0
- package/src/lib/components/dialog-confirm.js.map +1 -1
- package/src/lib/components/permission-choice-list.component.d.ts +72 -0
- package/src/lib/components/permission-choice-list.component.js +225 -0
- package/src/lib/components/permission-choice-list.component.js.map +1 -0
- package/src/lib/components/status-chip.component.d.ts +5 -0
- package/src/lib/components/status-chip.component.js +4 -2
- package/src/lib/components/status-chip.component.js.map +1 -1
- package/src/lib/components/stock-photo-search.component.d.ts +117 -0
- package/src/lib/components/stock-photo-search.component.js +506 -0
- package/src/lib/components/stock-photo-search.component.js.map +1 -0
- package/src/lib/hooks/use-discard-changes-menu-item.d.ts +55 -0
- package/src/lib/hooks/use-discard-changes-menu-item.js +83 -0
- package/src/lib/hooks/use-discard-changes-menu-item.js.map +1 -0
- package/src/lib/hooks/use-online-status.d.ts +16 -0
- package/src/lib/hooks/use-online-status.js +86 -0
- package/src/lib/hooks/use-online-status.js.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/shared-ui-jsx",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.283",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,10 +25,11 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-ui-
|
|
30
|
-
"@aglyn/shared-
|
|
31
|
-
"@aglyn/shared-util-
|
|
28
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.283",
|
|
29
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.283",
|
|
30
|
+
"@aglyn/shared-ui-theme": "1.0.0-beta.283",
|
|
31
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.283",
|
|
32
|
+
"@aglyn/shared-util-vendor": "1.0.0-beta.283",
|
|
32
33
|
"@mdi/js": "^7.4.47",
|
|
33
34
|
"@swc/helpers": "0.5.23",
|
|
34
35
|
"change-case": "^5.4.4",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material/styles';
|
|
2
|
+
/** What the chip reads. One word, the same on every surface that wears it. */
|
|
3
|
+
export declare const BETA_CHIP_LABEL = "Beta";
|
|
4
|
+
/**
|
|
5
|
+
* What Beta means to the reader, as the chip's hover and screen-reader
|
|
6
|
+
* description: the feature is open, not a preview, and it is still changing.
|
|
7
|
+
*/
|
|
8
|
+
export declare const BETA_CHIP_DESCRIPTION = "Available on every plan that includes it, and still changing as we improve it.";
|
|
9
|
+
export interface BetaChipProps {
|
|
10
|
+
/** Spacing from what it sits beside; the chip itself takes no margin. */
|
|
11
|
+
sx?: SxProps<Theme>;
|
|
12
|
+
'data-testid'?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The Beta label for a released feature that is still changing (AGL-4052),
|
|
16
|
+
* beside its nav tab, its page heading or its panel title.
|
|
17
|
+
*
|
|
18
|
+
* Inline on purpose: the root is a `span` and so is the chip, because it sits
|
|
19
|
+
* inside a heading or a tab label. The description is attached with
|
|
20
|
+
* `describeChild`, so a tab or heading keeps "Beta" as part of its name
|
|
21
|
+
* rather than taking the sentence as its name.
|
|
22
|
+
*/
|
|
23
|
+
export declare function BetaChip(props: BetaChipProps): import("react").JSX.Element;
|
|
24
|
+
export declare namespace BetaChip {
|
|
25
|
+
var displayName: string;
|
|
26
|
+
}
|
|
27
|
+
export default BetaChip;
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
|
+
import Box from "@mui/material/Box";
|
|
19
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
20
|
+
import { StatusChip } from "./status-chip.component.js";
|
|
21
|
+
/** What the chip reads. One word, the same on every surface that wears it. */ export const BETA_CHIP_LABEL = 'Beta';
|
|
22
|
+
/**
|
|
23
|
+
* What Beta means to the reader, as the chip's hover and screen-reader
|
|
24
|
+
* description: the feature is open, not a preview, and it is still changing.
|
|
25
|
+
*/ export const BETA_CHIP_DESCRIPTION = 'Available on every plan that includes it, and still changing as we improve it.';
|
|
26
|
+
/**
|
|
27
|
+
* The Beta label for a released feature that is still changing (AGL-4052),
|
|
28
|
+
* beside its nav tab, its page heading or its panel title.
|
|
29
|
+
*
|
|
30
|
+
* Inline on purpose: the root is a `span` and so is the chip, because it sits
|
|
31
|
+
* inside a heading or a tab label. The description is attached with
|
|
32
|
+
* `describeChild`, so a tab or heading keeps "Beta" as part of its name
|
|
33
|
+
* rather than taking the sentence as its name.
|
|
34
|
+
*/ export function BetaChip(props) {
|
|
35
|
+
const { sx } = props;
|
|
36
|
+
return /*#__PURE__*/ _jsx(Tooltip, {
|
|
37
|
+
title: BETA_CHIP_DESCRIPTION,
|
|
38
|
+
describeChild: true,
|
|
39
|
+
children: /*#__PURE__*/ _jsx(Box, {
|
|
40
|
+
component: "span",
|
|
41
|
+
"data-testid": props['data-testid'],
|
|
42
|
+
"data-release-stage": "beta",
|
|
43
|
+
sx: [
|
|
44
|
+
{
|
|
45
|
+
display: 'inline-flex',
|
|
46
|
+
alignItems: 'center',
|
|
47
|
+
flexShrink: 0
|
|
48
|
+
},
|
|
49
|
+
...Array.isArray(sx) ? sx : [
|
|
50
|
+
sx
|
|
51
|
+
]
|
|
52
|
+
],
|
|
53
|
+
children: /*#__PURE__*/ _jsx(StatusChip, {
|
|
54
|
+
label: BETA_CHIP_LABEL,
|
|
55
|
+
tone: "info",
|
|
56
|
+
variant: "outlined",
|
|
57
|
+
component: "span"
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
BetaChip.displayName = 'BetaChip';
|
|
63
|
+
export default BetaChip;
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=beta-chip.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/beta-chip.component.tsx"],"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'use client'\n\nimport Box from '@mui/material/Box'\nimport type { SxProps, Theme } from '@mui/material/styles'\nimport Tooltip from '@mui/material/Tooltip'\nimport { StatusChip } from './status-chip.component'\n\n/** What the chip reads. One word, the same on every surface that wears it. */\nexport const BETA_CHIP_LABEL = 'Beta'\n\n/**\n * What Beta means to the reader, as the chip's hover and screen-reader\n * description: the feature is open, not a preview, and it is still changing.\n */\nexport const BETA_CHIP_DESCRIPTION =\n 'Available on every plan that includes it, and still changing as we improve it.'\n\nexport interface BetaChipProps {\n /** Spacing from what it sits beside; the chip itself takes no margin. */\n sx?: SxProps<Theme>\n 'data-testid'?: string\n}\n\n/**\n * The Beta label for a released feature that is still changing (AGL-4052),\n * beside its nav tab, its page heading or its panel title.\n *\n * Inline on purpose: the root is a `span` and so is the chip, because it sits\n * inside a heading or a tab label. The description is attached with\n * `describeChild`, so a tab or heading keeps \"Beta\" as part of its name\n * rather than taking the sentence as its name.\n */\nexport function BetaChip(props: BetaChipProps) {\n const { sx } = props\n return (\n <Tooltip title={BETA_CHIP_DESCRIPTION} describeChild>\n <Box\n component=\"span\"\n data-testid={props['data-testid']}\n data-release-stage=\"beta\"\n sx={[\n { display: 'inline-flex', alignItems: 'center', flexShrink: 0 },\n ...(Array.isArray(sx) ? sx : [sx]),\n ]}\n >\n <StatusChip\n label={BETA_CHIP_LABEL}\n tone=\"info\"\n variant=\"outlined\"\n component=\"span\"\n />\n </Box>\n </Tooltip>\n )\n}\nBetaChip.displayName = 'BetaChip'\n\nexport default BetaChip\n"],"names":["Box","Tooltip","StatusChip","BETA_CHIP_LABEL","BETA_CHIP_DESCRIPTION","BetaChip","props","sx","title","describeChild","component","data-testid","data-release-stage","display","alignItems","flexShrink","Array","isArray","label","tone","variant","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,OAAOA,SAAS,oBAAmB;AAEnC,OAAOC,aAAa,wBAAuB;AAC3C,SAASC,UAAU,QAAQ,6BAAyB;AAEpD,4EAA4E,GAC5E,OAAO,MAAMC,kBAAkB,OAAM;AAErC;;;CAGC,GACD,OAAO,MAAMC,wBACX,iFAAgF;AAQlF;;;;;;;;CAQC,GACD,OAAO,SAASC,SAASC,KAAoB;IAC3C,MAAM,EAAEC,EAAE,EAAE,GAAGD;IACf,qBACE,KAACL;QAAQO,OAAOJ;QAAuBK,aAAa;kBAClD,cAAA,KAACT;YACCU,WAAU;YACVC,eAAaL,KAAK,CAAC,cAAc;YACjCM,sBAAmB;YACnBL,IAAI;gBACF;oBAAEM,SAAS;oBAAeC,YAAY;oBAAUC,YAAY;gBAAE;mBAC1DC,MAAMC,OAAO,CAACV,MAAMA,KAAK;oBAACA;iBAAG;aAClC;sBAED,cAAA,KAACL;gBACCgB,OAAOf;gBACPgB,MAAK;gBACLC,SAAQ;gBACRV,WAAU;;;;AAKpB;AACAL,SAASgB,WAAW,GAAG;AAEvB,eAAehB,SAAQ"}
|
|
@@ -38,7 +38,12 @@ export function ConfirmationProviderComponent(props) {
|
|
|
38
38
|
const handleClose = useCallback(()=>{
|
|
39
39
|
setResolveReject([]);
|
|
40
40
|
}, []);
|
|
41
|
+
// The first answer settles the promise and clears the pair, but the dialog
|
|
42
|
+
// stays on screen through its exit transition. A second click in that
|
|
43
|
+
// window (a double click, a repeated Enter) has no question left to answer,
|
|
44
|
+
// so it must not call the cleared resolve or reject.
|
|
41
45
|
const handleCancel = useCallback(()=>{
|
|
46
|
+
if (!reject) return;
|
|
42
47
|
reject();
|
|
43
48
|
handleClose();
|
|
44
49
|
}, [
|
|
@@ -46,6 +51,7 @@ export function ConfirmationProviderComponent(props) {
|
|
|
46
51
|
handleClose
|
|
47
52
|
]);
|
|
48
53
|
const handleConfirm = useCallback(()=>{
|
|
54
|
+
if (!resolve) return;
|
|
49
55
|
resolve();
|
|
50
56
|
handleClose();
|
|
51
57
|
}, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/confirmation-provider.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2024 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'use client'\n\nimport {\n type ElementType,\n Fragment,\n type MouseEventHandler,\n useCallback,\n useMemo,\n useState,\n} from 'react'\nimport ConfirmationContext, {\n buildConfirmationContextConfig,\n type ConfirmationContextConfig,\n type ConfirmFunction,\n DEFAULT_CONTEXT_CONFIG,\n} from '../contexts/confirmation.context'\nimport DialogConfirm from './dialog-confirm'\n\nexport interface ConfirmationProviderComponentProps {\n defaultOptions?: ConfirmationContextConfig\n children?: JSX.Children\n component?: ElementType<{\n open: boolean\n options: ConfirmationContextConfig\n onClose: MouseEventHandler<unknown>\n onCancel: MouseEventHandler<unknown>\n onConfirm: MouseEventHandler<unknown>\n }>\n}\n\nexport function ConfirmationProviderComponent(\n props: ConfirmationProviderComponentProps,\n) {\n const {\n children,\n defaultOptions = {},\n component: Component = DialogConfirm,\n } = props\n const [options, setOptions] = useState({\n ...DEFAULT_CONTEXT_CONFIG,\n ...defaultOptions,\n })\n const [resolveReject, setResolveReject] = useState([])\n const [resolve, reject] = resolveReject\n\n const confirm = useCallback<ConfirmFunction>(\n (options: ConfirmationContextConfig = {}) => {\n return new Promise((resolve, reject) => {\n setOptions(buildConfirmationContextConfig(defaultOptions, options))\n setResolveReject([resolve, reject])\n })\n },\n [defaultOptions],\n )\n\n const handleClose = useCallback(() => {\n setResolveReject([])\n }, [])\n\n const handleCancel = useCallback(() => {\n reject()\n handleClose()\n }, [reject, handleClose])\n\n const handleConfirm = useCallback(() => {\n resolve()\n handleClose()\n }, [resolve, handleClose])\n\n const child = useMemo(() => {\n return (\n <ConfirmationContext.Provider value={{ confirm }}>\n {children}\n </ConfirmationContext.Provider>\n )\n }, [children, confirm])\n\n return (\n <Fragment>\n {child}\n <Component\n open={resolveReject.length === 2}\n options={options}\n onClose={handleClose}\n onCancel={handleCancel}\n onConfirm={handleConfirm}\n />\n </Fragment>\n )\n}\nConfirmationProviderComponent.displayName = 'ConfirmationProviderComponent'\nConfirmationProviderComponent.aglyn = true\n\nexport default ConfirmationProviderComponent\n"],"names":["Fragment","useCallback","useMemo","useState","ConfirmationContext","buildConfirmationContextConfig","DEFAULT_CONTEXT_CONFIG","DialogConfirm","ConfirmationProviderComponent","props","children","defaultOptions","component","Component","options","setOptions","resolveReject","setResolveReject","resolve","reject","confirm","Promise","handleClose","handleCancel","handleConfirm","child","Provider","value","open","length","onClose","onCancel","onConfirm","displayName","aglyn"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAEEA,QAAQ,EAERC,WAAW,EACXC,OAAO,EACPC,QAAQ,QACH,QAAO;AACd,OAAOC,uBACLC,8BAA8B,EAG9BC,sBAAsB,QACjB,sCAAkC;AACzC,OAAOC,mBAAmB,sBAAkB;AAc5C,OAAO,SAASC,8BACdC,KAAyC;IAEzC,MAAM,EACJC,QAAQ,EACRC,iBAAiB,CAAC,CAAC,EACnBC,WAAWC,YAAYN,aAAa,EACrC,GAAGE;IACJ,MAAM,CAACK,SAASC,WAAW,GAAGZ,SAAS,aAClCG,wBACAK;IAEL,MAAM,CAACK,eAAeC,iBAAiB,GAAGd,SAAS,EAAE;IACrD,MAAM,CAACe,SAASC,OAAO,GAAGH;IAE1B,MAAMI,UAAUnB,YACd,CAACa,UAAqC,CAAC,CAAC;QACtC,OAAO,IAAIO,QAAQ,CAACH,SAASC;YAC3BJ,WAAWV,+BAA+BM,gBAAgBG;YAC1DG,iBAAiB;gBAACC;gBAASC;aAAO;QACpC;IACF,GACA;QAACR;KAAe;IAGlB,MAAMW,cAAcrB,YAAY;QAC9BgB,iBAAiB,EAAE;IACrB,GAAG,EAAE;IAEL,MAAMM,eAAetB,YAAY;QAC/
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/confirmation-provider.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2024 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'use client'\n\nimport {\n type ElementType,\n Fragment,\n type MouseEventHandler,\n useCallback,\n useMemo,\n useState,\n} from 'react'\nimport ConfirmationContext, {\n buildConfirmationContextConfig,\n type ConfirmationContextConfig,\n type ConfirmFunction,\n DEFAULT_CONTEXT_CONFIG,\n} from '../contexts/confirmation.context'\nimport DialogConfirm from './dialog-confirm'\n\nexport interface ConfirmationProviderComponentProps {\n defaultOptions?: ConfirmationContextConfig\n children?: JSX.Children\n component?: ElementType<{\n open: boolean\n options: ConfirmationContextConfig\n onClose: MouseEventHandler<unknown>\n onCancel: MouseEventHandler<unknown>\n onConfirm: MouseEventHandler<unknown>\n }>\n}\n\nexport function ConfirmationProviderComponent(\n props: ConfirmationProviderComponentProps,\n) {\n const {\n children,\n defaultOptions = {},\n component: Component = DialogConfirm,\n } = props\n const [options, setOptions] = useState({\n ...DEFAULT_CONTEXT_CONFIG,\n ...defaultOptions,\n })\n const [resolveReject, setResolveReject] = useState([])\n const [resolve, reject] = resolveReject\n\n const confirm = useCallback<ConfirmFunction>(\n (options: ConfirmationContextConfig = {}) => {\n return new Promise((resolve, reject) => {\n setOptions(buildConfirmationContextConfig(defaultOptions, options))\n setResolveReject([resolve, reject])\n })\n },\n [defaultOptions],\n )\n\n const handleClose = useCallback(() => {\n setResolveReject([])\n }, [])\n\n // The first answer settles the promise and clears the pair, but the dialog\n // stays on screen through its exit transition. A second click in that\n // window (a double click, a repeated Enter) has no question left to answer,\n // so it must not call the cleared resolve or reject.\n const handleCancel = useCallback(() => {\n if (!reject) return\n reject()\n handleClose()\n }, [reject, handleClose])\n\n const handleConfirm = useCallback(() => {\n if (!resolve) return\n resolve()\n handleClose()\n }, [resolve, handleClose])\n\n const child = useMemo(() => {\n return (\n <ConfirmationContext.Provider value={{ confirm }}>\n {children}\n </ConfirmationContext.Provider>\n )\n }, [children, confirm])\n\n return (\n <Fragment>\n {child}\n <Component\n open={resolveReject.length === 2}\n options={options}\n onClose={handleClose}\n onCancel={handleCancel}\n onConfirm={handleConfirm}\n />\n </Fragment>\n )\n}\nConfirmationProviderComponent.displayName = 'ConfirmationProviderComponent'\nConfirmationProviderComponent.aglyn = true\n\nexport default ConfirmationProviderComponent\n"],"names":["Fragment","useCallback","useMemo","useState","ConfirmationContext","buildConfirmationContextConfig","DEFAULT_CONTEXT_CONFIG","DialogConfirm","ConfirmationProviderComponent","props","children","defaultOptions","component","Component","options","setOptions","resolveReject","setResolveReject","resolve","reject","confirm","Promise","handleClose","handleCancel","handleConfirm","child","Provider","value","open","length","onClose","onCancel","onConfirm","displayName","aglyn"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,SAEEA,QAAQ,EAERC,WAAW,EACXC,OAAO,EACPC,QAAQ,QACH,QAAO;AACd,OAAOC,uBACLC,8BAA8B,EAG9BC,sBAAsB,QACjB,sCAAkC;AACzC,OAAOC,mBAAmB,sBAAkB;AAc5C,OAAO,SAASC,8BACdC,KAAyC;IAEzC,MAAM,EACJC,QAAQ,EACRC,iBAAiB,CAAC,CAAC,EACnBC,WAAWC,YAAYN,aAAa,EACrC,GAAGE;IACJ,MAAM,CAACK,SAASC,WAAW,GAAGZ,SAAS,aAClCG,wBACAK;IAEL,MAAM,CAACK,eAAeC,iBAAiB,GAAGd,SAAS,EAAE;IACrD,MAAM,CAACe,SAASC,OAAO,GAAGH;IAE1B,MAAMI,UAAUnB,YACd,CAACa,UAAqC,CAAC,CAAC;QACtC,OAAO,IAAIO,QAAQ,CAACH,SAASC;YAC3BJ,WAAWV,+BAA+BM,gBAAgBG;YAC1DG,iBAAiB;gBAACC;gBAASC;aAAO;QACpC;IACF,GACA;QAACR;KAAe;IAGlB,MAAMW,cAAcrB,YAAY;QAC9BgB,iBAAiB,EAAE;IACrB,GAAG,EAAE;IAEL,2EAA2E;IAC3E,sEAAsE;IACtE,4EAA4E;IAC5E,qDAAqD;IACrD,MAAMM,eAAetB,YAAY;QAC/B,IAAI,CAACkB,QAAQ;QACbA;QACAG;IACF,GAAG;QAACH;QAAQG;KAAY;IAExB,MAAME,gBAAgBvB,YAAY;QAChC,IAAI,CAACiB,SAAS;QACdA;QACAI;IACF,GAAG;QAACJ;QAASI;KAAY;IAEzB,MAAMG,QAAQvB,QAAQ;QACpB,qBACE,KAACE,oBAAoBsB,QAAQ;YAACC,OAAO;gBAAEP;YAAQ;sBAC5CV;;IAGP,GAAG;QAACA;QAAUU;KAAQ;IAEtB,qBACE,MAACpB;;YACEyB;0BACD,KAACZ;gBACCe,MAAMZ,cAAca,MAAM,KAAK;gBAC/Bf,SAASA;gBACTgB,SAASR;gBACTS,UAAUR;gBACVS,WAAWR;;;;AAInB;AACAhB,8BAA8ByB,WAAW,GAAG;AAC5CzB,8BAA8B0B,KAAK,GAAG;AAEtC,eAAe1B,8BAA6B"}
|
|
@@ -53,12 +53,14 @@ export const DialogConfirm = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
|
53
53
|
/*#__PURE__*/ _jsxs(DialogActions, {
|
|
54
54
|
children: [
|
|
55
55
|
/*#__PURE__*/ _jsx(Button, _extends({}, cancellationButtonProps, {
|
|
56
|
+
disabled: !open || (cancellationButtonProps == null ? void 0 : cancellationButtonProps.disabled),
|
|
56
57
|
onClick: onCancel,
|
|
57
58
|
children: cancellationText
|
|
58
59
|
})),
|
|
59
60
|
/*#__PURE__*/ _jsx(Button, _extends({
|
|
60
61
|
color: "primary"
|
|
61
62
|
}, confirmationButtonProps, {
|
|
63
|
+
disabled: !open || (confirmationButtonProps == null ? void 0 : confirmationButtonProps.disabled),
|
|
62
64
|
onClick: onConfirm,
|
|
63
65
|
children: confirmationText
|
|
64
66
|
}))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/dialog-confirm.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 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\nimport Button, { ButtonProps } from '@mui/material/Button'\nimport Dialog, { DialogProps } from '@mui/material/Dialog'\nimport DialogActions from '@mui/material/DialogActions'\nimport DialogContent from '@mui/material/DialogContent'\nimport DialogContentText, {\n DialogContentTextProps,\n} from '@mui/material/DialogContentText'\nimport DialogTitle, { DialogTitleProps } from '@mui/material/DialogTitle'\nimport { forwardRef } from 'react'\n\nexport interface DialogConfirmOptions {\n cancellationText?: ButtonProps['children']\n confirmationText?: ButtonProps['children']\n cancellationButtonProps?: Partial<ButtonProps>\n confirmationButtonProps?: Partial<ButtonProps>\n dialogProps?: Partial<DialogProps>\n title?: DialogTitleProps['children']\n description?: DialogContentTextProps['children']\n}\n\nexport interface DialogConfirmProps extends DialogProps {\n options?: DialogConfirmOptions\n onConfirm?: ButtonProps['onClick']\n onCancel?: ButtonProps['onClick']\n}\n\nexport const DialogConfirm = forwardRef<any, DialogConfirmProps>(\n (props, ref) => {\n const {\n open,\n options = {\n cancellationText: 'Cancel',\n confirmationText: 'OK',\n },\n onCancel,\n onConfirm,\n onClose,\n ...rest\n } = props\n const {\n title,\n description,\n confirmationText,\n cancellationText,\n dialogProps,\n confirmationButtonProps,\n cancellationButtonProps,\n } = options\n return (\n <Dialog\n ref={ref}\n fullWidth\n {...rest}\n {...dialogProps}\n open={open}\n onClose={onClose}\n >\n {title && <DialogTitle>{title}</DialogTitle>}\n {description && (\n <DialogContent>\n <DialogContentText>{description}</DialogContentText>\n </DialogContent>\n )}\n <DialogActions>\n <Button
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/dialog-confirm.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2023 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\nimport Button, { ButtonProps } from '@mui/material/Button'\nimport Dialog, { DialogProps } from '@mui/material/Dialog'\nimport DialogActions from '@mui/material/DialogActions'\nimport DialogContent from '@mui/material/DialogContent'\nimport DialogContentText, {\n DialogContentTextProps,\n} from '@mui/material/DialogContentText'\nimport DialogTitle, { DialogTitleProps } from '@mui/material/DialogTitle'\nimport { forwardRef } from 'react'\n\nexport interface DialogConfirmOptions {\n cancellationText?: ButtonProps['children']\n confirmationText?: ButtonProps['children']\n cancellationButtonProps?: Partial<ButtonProps>\n confirmationButtonProps?: Partial<ButtonProps>\n dialogProps?: Partial<DialogProps>\n title?: DialogTitleProps['children']\n description?: DialogContentTextProps['children']\n}\n\nexport interface DialogConfirmProps extends DialogProps {\n options?: DialogConfirmOptions\n onConfirm?: ButtonProps['onClick']\n onCancel?: ButtonProps['onClick']\n}\n\nexport const DialogConfirm = forwardRef<any, DialogConfirmProps>(\n (props, ref) => {\n const {\n open,\n options = {\n cancellationText: 'Cancel',\n confirmationText: 'OK',\n },\n onCancel,\n onConfirm,\n onClose,\n ...rest\n } = props\n const {\n title,\n description,\n confirmationText,\n cancellationText,\n dialogProps,\n confirmationButtonProps,\n cancellationButtonProps,\n } = options\n return (\n <Dialog\n ref={ref}\n fullWidth\n {...rest}\n {...dialogProps}\n open={open}\n onClose={onClose}\n >\n {title && <DialogTitle>{title}</DialogTitle>}\n {description && (\n <DialogContent>\n <DialogContentText>{description}</DialogContentText>\n </DialogContent>\n )}\n {/* Once answered the dialog fades out with its buttons still drawn;\n they are disabled for that moment so they don't look live. */}\n <DialogActions>\n <Button\n {...cancellationButtonProps}\n disabled={!open || cancellationButtonProps?.disabled}\n onClick={onCancel}\n >\n {cancellationText}\n </Button>\n <Button\n color=\"primary\"\n {...confirmationButtonProps}\n disabled={!open || confirmationButtonProps?.disabled}\n onClick={onConfirm}\n >\n {confirmationText}\n </Button>\n </DialogActions>\n </Dialog>\n )\n },\n)\n\nDialogConfirm.displayName = 'DialogConfirm'\nDialogConfirm.aglyn = true\n\nexport default DialogConfirm\n"],"names":["Button","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","forwardRef","DialogConfirm","props","ref","open","options","cancellationText","confirmationText","onCancel","onConfirm","onClose","rest","title","description","dialogProps","confirmationButtonProps","cancellationButtonProps","fullWidth","disabled","onClick","color","displayName","aglyn"],"mappings":";;;AAAA;;;;;;;;;;;;;;;CAeC,GAED,OAAOA,YAA6B,uBAAsB;AAC1D,OAAOC,YAA6B,uBAAsB;AAC1D,OAAOC,mBAAmB,8BAA6B;AACvD,OAAOC,mBAAmB,8BAA6B;AACvD,OAAOC,uBAEA,kCAAiC;AACxC,OAAOC,iBAAuC,4BAA2B;AACzE,SAASC,UAAU,QAAQ,QAAO;AAkBlC,OAAO,MAAMC,8BAAgBD,WAC3B,CAACE,OAAOC;IACN,MAAM,EACJC,IAAI,EACJC,UAAU;QACRC,kBAAkB;QAClBC,kBAAkB;IACpB,CAAC,EACDC,QAAQ,EACRC,SAAS,EACTC,OAAO,EAER,GAAGR,OADCS,wCACDT;;;;;;;IACJ,MAAM,EACJU,KAAK,EACLC,WAAW,EACXN,gBAAgB,EAChBD,gBAAgB,EAChBQ,WAAW,EACXC,uBAAuB,EACvBC,uBAAuB,EACxB,GAAGX;IACJ,qBACE,MAACV;QACCQ,KAAKA;QACLc,SAAS;OACLN,MACAG;QACJV,MAAMA;QACNM,SAASA;;YAERE,uBAAS,KAACb;0BAAaa;;YACvBC,6BACC,KAAChB;0BACC,cAAA,KAACC;8BAAmBe;;;0BAKxB,MAACjB;;kCACC,KAACF,qBACKsB;wBACJE,UAAU,CAACd,SAAQY,2CAAAA,wBAAyBE,QAAQ;wBACpDC,SAASX;kCAERF;;kCAEH,KAACZ;wBACC0B,OAAM;uBACFL;wBACJG,UAAU,CAACd,SAAQW,2CAAAA,wBAAyBG,QAAQ;wBACpDC,SAASV;kCAERF;;;;;;AAKX,GACD;AAEDN,cAAcoB,WAAW,GAAG;AAC5BpB,cAAcqB,KAAK,GAAG;AAEtB,eAAerB,cAAa"}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
import { type ReactNode } from 'react';
|
|
18
|
+
/**
|
|
19
|
+
* A grouped, searchable list of permissions with three states each (AGL-4047):
|
|
20
|
+
* inherit (the layer below decides), allow, or deny. Drawn by every editor of
|
|
21
|
+
* a permission map — a custom role, one member's overrides, one collaborator's
|
|
22
|
+
* per-site toggles — so they look and behave alike.
|
|
23
|
+
*
|
|
24
|
+
* Presentation only: the caller decides which keys are offered, how they are
|
|
25
|
+
* grouped, what a search keeps and what "inherit" resolves to, and hands the
|
|
26
|
+
* words in. NOT in the `@aglyn/shared-ui-jsx` barrel; subpath-import it
|
|
27
|
+
* (`@aglyn/shared-ui-jsx/components/permission-choice-list.component`).
|
|
28
|
+
*/
|
|
29
|
+
export type PermissionChoiceValue = 'inherit' | 'grant' | 'deny';
|
|
30
|
+
export interface PermissionChoiceItem {
|
|
31
|
+
key: string;
|
|
32
|
+
label: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
choice: PermissionChoiceValue;
|
|
35
|
+
/**
|
|
36
|
+
* The verdict the member ends up with and where it came from
|
|
37
|
+
* ("Allowed by the Editor role"), shown under the description.
|
|
38
|
+
*/
|
|
39
|
+
effective?: {
|
|
40
|
+
granted: boolean;
|
|
41
|
+
source: string;
|
|
42
|
+
};
|
|
43
|
+
/** What inherit resolves to here, when there is one answer ("Editor default: allowed"). */
|
|
44
|
+
inheritHint?: string;
|
|
45
|
+
/** A reason the row cannot change, shown as the toggle's tooltip. */
|
|
46
|
+
lockedReason?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface PermissionChoiceSection {
|
|
49
|
+
id: string;
|
|
50
|
+
label: string;
|
|
51
|
+
items: PermissionChoiceItem[];
|
|
52
|
+
}
|
|
53
|
+
export interface PermissionChoiceListProps {
|
|
54
|
+
sections: readonly PermissionChoiceSection[];
|
|
55
|
+
/** Sets one key (or, from a group heading, every key of the group) to a choice. */
|
|
56
|
+
onChange: (keys: string[], choice: PermissionChoiceValue) => void;
|
|
57
|
+
/** The search box; absent hides it. */
|
|
58
|
+
search?: string;
|
|
59
|
+
onSearchChange?: (value: string) => void;
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
/** The words for the three states. */
|
|
62
|
+
labels?: Partial<Record<PermissionChoiceValue, string>>;
|
|
63
|
+
/** Shown when a search keeps nothing. */
|
|
64
|
+
emptyMessage?: ReactNode;
|
|
65
|
+
/** Offer "set the whole group" on each heading. */
|
|
66
|
+
groupActions?: boolean;
|
|
67
|
+
}
|
|
68
|
+
export declare function PermissionChoiceList(props: PermissionChoiceListProps): import("react").JSX.Element;
|
|
69
|
+
export declare namespace PermissionChoiceList {
|
|
70
|
+
var displayName: string;
|
|
71
|
+
}
|
|
72
|
+
export default PermissionChoiceList;
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2026 Aglyn LLC
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/ import { Box, Chip, Divider, Stack, TextField, ToggleButton, ToggleButtonGroup, Tooltip, Typography } from "@mui/material";
|
|
19
|
+
import { useId } from "react";
|
|
20
|
+
const CHOICES = [
|
|
21
|
+
'inherit',
|
|
22
|
+
'grant',
|
|
23
|
+
'deny'
|
|
24
|
+
];
|
|
25
|
+
const DEFAULT_LABELS = {
|
|
26
|
+
inherit: 'Inherit',
|
|
27
|
+
grant: 'Allow',
|
|
28
|
+
deny: 'Deny'
|
|
29
|
+
};
|
|
30
|
+
function ChoiceToggle(props) {
|
|
31
|
+
return /*#__PURE__*/ _jsx(ToggleButtonGroup, {
|
|
32
|
+
size: "small",
|
|
33
|
+
exclusive: true,
|
|
34
|
+
value: props.value,
|
|
35
|
+
disabled: props.disabled,
|
|
36
|
+
"aria-label": props.ariaLabel,
|
|
37
|
+
onChange: (_event, next)=>{
|
|
38
|
+
if (next) props.onChange(next);
|
|
39
|
+
},
|
|
40
|
+
sx: {
|
|
41
|
+
flexShrink: 0
|
|
42
|
+
},
|
|
43
|
+
children: CHOICES.map((choice)=>/*#__PURE__*/ _jsx(ToggleButton, {
|
|
44
|
+
value: choice,
|
|
45
|
+
color: choice === 'grant' ? 'success' : choice === 'deny' ? 'error' : 'standard',
|
|
46
|
+
sx: {
|
|
47
|
+
px: 1.25,
|
|
48
|
+
py: 0.25,
|
|
49
|
+
textTransform: 'none'
|
|
50
|
+
},
|
|
51
|
+
children: props.labels[choice]
|
|
52
|
+
}, choice))
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export function PermissionChoiceList(props) {
|
|
56
|
+
var _props_search, _props_emptyMessage;
|
|
57
|
+
const labels = _extends({}, DEFAULT_LABELS, props.labels);
|
|
58
|
+
const searchId = useId();
|
|
59
|
+
const visible = props.sections.filter((section)=>section.items.length > 0);
|
|
60
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
61
|
+
spacing: 2,
|
|
62
|
+
children: [
|
|
63
|
+
props.onSearchChange ? /*#__PURE__*/ _jsx(TextField, {
|
|
64
|
+
id: searchId,
|
|
65
|
+
size: "small",
|
|
66
|
+
type: "search",
|
|
67
|
+
label: "Search permissions",
|
|
68
|
+
value: (_props_search = props.search) != null ? _props_search : '',
|
|
69
|
+
onChange: (event)=>props.onSearchChange == null ? void 0 : props.onSearchChange.call(props, event.target.value)
|
|
70
|
+
}) : null,
|
|
71
|
+
visible.length === 0 ? /*#__PURE__*/ _jsx(Typography, {
|
|
72
|
+
variant: "body2",
|
|
73
|
+
color: "text.secondary",
|
|
74
|
+
children: (_props_emptyMessage = props.emptyMessage) != null ? _props_emptyMessage : 'No permission matches your search.'
|
|
75
|
+
}) : null,
|
|
76
|
+
visible.map((section)=>{
|
|
77
|
+
var _ref;
|
|
78
|
+
var _section_items_;
|
|
79
|
+
const granted = section.items.filter((item)=>item.choice === 'grant').length;
|
|
80
|
+
const denied = section.items.filter((item)=>item.choice === 'deny').length;
|
|
81
|
+
const shared = section.items.every((item)=>{
|
|
82
|
+
var _section_items_;
|
|
83
|
+
return item.choice === ((_section_items_ = section.items[0]) == null ? void 0 : _section_items_.choice);
|
|
84
|
+
}) ? (_ref = (_section_items_ = section.items[0]) == null ? void 0 : _section_items_.choice) != null ? _ref : null : null;
|
|
85
|
+
const changeable = section.items.filter((item)=>!item.lockedReason).map((item)=>item.key);
|
|
86
|
+
return /*#__PURE__*/ _jsxs(Box, {
|
|
87
|
+
component: "section",
|
|
88
|
+
"aria-label": section.label,
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
91
|
+
direction: {
|
|
92
|
+
xs: 'column',
|
|
93
|
+
sm: 'row'
|
|
94
|
+
},
|
|
95
|
+
spacing: 1,
|
|
96
|
+
sx: {
|
|
97
|
+
alignItems: {
|
|
98
|
+
xs: 'flex-start',
|
|
99
|
+
sm: 'center'
|
|
100
|
+
},
|
|
101
|
+
justifyContent: 'space-between',
|
|
102
|
+
mb: 1
|
|
103
|
+
},
|
|
104
|
+
children: [
|
|
105
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
106
|
+
direction: "row",
|
|
107
|
+
spacing: 1,
|
|
108
|
+
sx: {
|
|
109
|
+
alignItems: 'center',
|
|
110
|
+
flexWrap: 'wrap',
|
|
111
|
+
rowGap: 0.5
|
|
112
|
+
},
|
|
113
|
+
children: [
|
|
114
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
115
|
+
variant: "subtitle2",
|
|
116
|
+
component: "h3",
|
|
117
|
+
children: section.label
|
|
118
|
+
}),
|
|
119
|
+
granted ? /*#__PURE__*/ _jsx(Chip, {
|
|
120
|
+
size: "small",
|
|
121
|
+
color: "success",
|
|
122
|
+
variant: "outlined",
|
|
123
|
+
label: `${granted} allowed`
|
|
124
|
+
}) : null,
|
|
125
|
+
denied ? /*#__PURE__*/ _jsx(Chip, {
|
|
126
|
+
size: "small",
|
|
127
|
+
color: "error",
|
|
128
|
+
variant: "outlined",
|
|
129
|
+
label: `${denied} denied`
|
|
130
|
+
}) : null
|
|
131
|
+
]
|
|
132
|
+
}),
|
|
133
|
+
props.groupActions && changeable.length > 1 ? /*#__PURE__*/ _jsx(ChoiceToggle, {
|
|
134
|
+
value: shared,
|
|
135
|
+
labels: labels,
|
|
136
|
+
disabled: props.disabled,
|
|
137
|
+
ariaLabel: `Set every ${section.label} permission`,
|
|
138
|
+
onChange: (choice)=>props.onChange(changeable, choice)
|
|
139
|
+
}) : null
|
|
140
|
+
]
|
|
141
|
+
}),
|
|
142
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
143
|
+
divider: /*#__PURE__*/ _jsx(Divider, {
|
|
144
|
+
flexItem: true
|
|
145
|
+
}),
|
|
146
|
+
sx: {
|
|
147
|
+
border: 1,
|
|
148
|
+
borderColor: 'divider',
|
|
149
|
+
borderRadius: 1
|
|
150
|
+
},
|
|
151
|
+
children: section.items.map((item)=>{
|
|
152
|
+
const toggle = /*#__PURE__*/ _jsx("span", {
|
|
153
|
+
children: /*#__PURE__*/ _jsx(ChoiceToggle, {
|
|
154
|
+
value: item.choice,
|
|
155
|
+
labels: labels,
|
|
156
|
+
disabled: props.disabled || Boolean(item.lockedReason),
|
|
157
|
+
ariaLabel: item.label,
|
|
158
|
+
onChange: (choice)=>props.onChange([
|
|
159
|
+
item.key
|
|
160
|
+
], choice)
|
|
161
|
+
})
|
|
162
|
+
});
|
|
163
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
164
|
+
direction: {
|
|
165
|
+
xs: 'column',
|
|
166
|
+
sm: 'row'
|
|
167
|
+
},
|
|
168
|
+
spacing: 1.5,
|
|
169
|
+
sx: {
|
|
170
|
+
px: 1.5,
|
|
171
|
+
py: 1,
|
|
172
|
+
alignItems: {
|
|
173
|
+
xs: 'stretch',
|
|
174
|
+
sm: 'center'
|
|
175
|
+
},
|
|
176
|
+
justifyContent: 'space-between'
|
|
177
|
+
},
|
|
178
|
+
children: [
|
|
179
|
+
/*#__PURE__*/ _jsxs(Box, {
|
|
180
|
+
sx: {
|
|
181
|
+
minWidth: 0
|
|
182
|
+
},
|
|
183
|
+
children: [
|
|
184
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
185
|
+
variant: "body2",
|
|
186
|
+
children: item.label
|
|
187
|
+
}),
|
|
188
|
+
item.description ? /*#__PURE__*/ _jsx(Typography, {
|
|
189
|
+
variant: "caption",
|
|
190
|
+
color: "text.secondary",
|
|
191
|
+
component: "p",
|
|
192
|
+
children: item.description
|
|
193
|
+
}) : null,
|
|
194
|
+
item.effective ? /*#__PURE__*/ _jsx(Typography, {
|
|
195
|
+
variant: "caption",
|
|
196
|
+
component: "p",
|
|
197
|
+
color: item.effective.granted ? 'success.main' : 'text.secondary',
|
|
198
|
+
children: `${item.effective.granted ? 'Allowed' : 'Not allowed'} · ${item.effective.source}`
|
|
199
|
+
}) : null,
|
|
200
|
+
item.choice === 'inherit' && item.inheritHint ? /*#__PURE__*/ _jsx(Typography, {
|
|
201
|
+
variant: "caption",
|
|
202
|
+
color: "text.secondary",
|
|
203
|
+
component: "p",
|
|
204
|
+
children: item.inheritHint
|
|
205
|
+
}) : null
|
|
206
|
+
]
|
|
207
|
+
}),
|
|
208
|
+
item.lockedReason ? /*#__PURE__*/ _jsx(Tooltip, {
|
|
209
|
+
title: item.lockedReason,
|
|
210
|
+
children: toggle
|
|
211
|
+
}) : toggle
|
|
212
|
+
]
|
|
213
|
+
}, item.key);
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
]
|
|
217
|
+
}, section.id);
|
|
218
|
+
})
|
|
219
|
+
]
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
PermissionChoiceList.displayName = 'PermissionChoiceList';
|
|
223
|
+
export default PermissionChoiceList;
|
|
224
|
+
|
|
225
|
+
//# sourceMappingURL=permission-choice-list.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/permission-choice-list.component.tsx"],"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\nimport {\n Box,\n Chip,\n Divider,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { useId, type ReactNode } from 'react'\n\n/**\n * A grouped, searchable list of permissions with three states each (AGL-4047):\n * inherit (the layer below decides), allow, or deny. Drawn by every editor of\n * a permission map — a custom role, one member's overrides, one collaborator's\n * per-site toggles — so they look and behave alike.\n *\n * Presentation only: the caller decides which keys are offered, how they are\n * grouped, what a search keeps and what \"inherit\" resolves to, and hands the\n * words in. NOT in the `@aglyn/shared-ui-jsx` barrel; subpath-import it\n * (`@aglyn/shared-ui-jsx/components/permission-choice-list.component`).\n */\n\nexport type PermissionChoiceValue = 'inherit' | 'grant' | 'deny'\n\nexport interface PermissionChoiceItem {\n key: string\n label: string\n description?: string\n choice: PermissionChoiceValue\n /**\n * The verdict the member ends up with and where it came from\n * (\"Allowed by the Editor role\"), shown under the description.\n */\n effective?: { granted: boolean; source: string }\n /** What inherit resolves to here, when there is one answer (\"Editor default: allowed\"). */\n inheritHint?: string\n /** A reason the row cannot change, shown as the toggle's tooltip. */\n lockedReason?: string\n}\n\nexport interface PermissionChoiceSection {\n id: string\n label: string\n items: PermissionChoiceItem[]\n}\n\nexport interface PermissionChoiceListProps {\n sections: readonly PermissionChoiceSection[]\n /** Sets one key (or, from a group heading, every key of the group) to a choice. */\n onChange: (keys: string[], choice: PermissionChoiceValue) => void\n /** The search box; absent hides it. */\n search?: string\n onSearchChange?: (value: string) => void\n disabled?: boolean\n /** The words for the three states. */\n labels?: Partial<Record<PermissionChoiceValue, string>>\n /** Shown when a search keeps nothing. */\n emptyMessage?: ReactNode\n /** Offer \"set the whole group\" on each heading. */\n groupActions?: boolean\n}\n\nconst CHOICES: readonly PermissionChoiceValue[] = ['inherit', 'grant', 'deny']\n\nconst DEFAULT_LABELS: Record<PermissionChoiceValue, string> = {\n inherit: 'Inherit',\n grant: 'Allow',\n deny: 'Deny',\n}\n\nfunction ChoiceToggle(props: {\n value: PermissionChoiceValue | null\n onChange: (choice: PermissionChoiceValue) => void\n disabled?: boolean\n labels: Record<PermissionChoiceValue, string>\n ariaLabel: string\n}) {\n return (\n <ToggleButtonGroup\n size=\"small\"\n exclusive\n value={props.value}\n disabled={props.disabled}\n aria-label={props.ariaLabel}\n onChange={(_event, next: PermissionChoiceValue | null) => {\n if (next) props.onChange(next)\n }}\n sx={{ flexShrink: 0 }}\n >\n {CHOICES.map((choice) => (\n <ToggleButton\n key={choice}\n value={choice}\n color={choice === 'grant' ? 'success' : choice === 'deny' ? 'error' : 'standard'}\n sx={{ px: 1.25, py: 0.25, textTransform: 'none' }}\n >\n {props.labels[choice]}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n )\n}\n\nexport function PermissionChoiceList(props: PermissionChoiceListProps) {\n const labels = { ...DEFAULT_LABELS, ...props.labels }\n const searchId = useId()\n const visible = props.sections.filter((section) => section.items.length > 0)\n return (\n <Stack spacing={2}>\n {props.onSearchChange ? (\n <TextField\n id={searchId}\n size=\"small\"\n type=\"search\"\n label=\"Search permissions\"\n value={props.search ?? ''}\n onChange={(event) => props.onSearchChange?.(event.target.value)}\n />\n ) : null}\n {visible.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {props.emptyMessage ?? 'No permission matches your search.'}\n </Typography>\n ) : null}\n {visible.map((section) => {\n const granted = section.items.filter((item) => item.choice === 'grant').length\n const denied = section.items.filter((item) => item.choice === 'deny').length\n const shared = section.items.every((item) => item.choice === section.items[0]?.choice)\n ? (section.items[0]?.choice ?? null)\n : null\n const changeable = section.items.filter((item) => !item.lockedReason).map((item) => item.key)\n return (\n <Box key={section.id} component=\"section\" aria-label={section.label}>\n <Stack\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ alignItems: { xs: 'flex-start', sm: 'center' }, justifyContent: 'space-between', mb: 1 }}\n >\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 0.5 }}>\n <Typography variant=\"subtitle2\" component=\"h3\">\n {section.label}\n </Typography>\n {granted ? <Chip size=\"small\" color=\"success\" variant=\"outlined\" label={`${granted} allowed`} /> : null}\n {denied ? <Chip size=\"small\" color=\"error\" variant=\"outlined\" label={`${denied} denied`} /> : null}\n </Stack>\n {props.groupActions && changeable.length > 1 ? (\n <ChoiceToggle\n value={shared}\n labels={labels}\n disabled={props.disabled}\n ariaLabel={`Set every ${section.label} permission`}\n onChange={(choice) => props.onChange(changeable, choice)}\n />\n ) : null}\n </Stack>\n <Stack divider={<Divider flexItem />} sx={{ border: 1, borderColor: 'divider', borderRadius: 1 }}>\n {section.items.map((item) => {\n const toggle = (\n <span>\n <ChoiceToggle\n value={item.choice}\n labels={labels}\n disabled={props.disabled || Boolean(item.lockedReason)}\n ariaLabel={item.label}\n onChange={(choice) => props.onChange([item.key], choice)}\n />\n </span>\n )\n return (\n <Stack\n key={item.key}\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1.5}\n sx={{ px: 1.5, py: 1, alignItems: { xs: 'stretch', sm: 'center' }, justifyContent: 'space-between' }}\n >\n <Box sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\">{item.label}</Typography>\n {item.description ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">\n {item.description}\n </Typography>\n ) : null}\n {item.effective ? (\n <Typography\n variant=\"caption\"\n component=\"p\"\n color={item.effective.granted ? 'success.main' : 'text.secondary'}\n >\n {`${item.effective.granted ? 'Allowed' : 'Not allowed'} · ${item.effective.source}`}\n </Typography>\n ) : null}\n {item.choice === 'inherit' && item.inheritHint ? (\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">\n {item.inheritHint}\n </Typography>\n ) : null}\n </Box>\n {item.lockedReason ? <Tooltip title={item.lockedReason}>{toggle}</Tooltip> : toggle}\n </Stack>\n )\n })}\n </Stack>\n </Box>\n )\n })}\n </Stack>\n )\n}\nPermissionChoiceList.displayName = 'PermissionChoiceList'\n\nexport default PermissionChoiceList\n"],"names":["Box","Chip","Divider","Stack","TextField","ToggleButton","ToggleButtonGroup","Tooltip","Typography","useId","CHOICES","DEFAULT_LABELS","inherit","grant","deny","ChoiceToggle","props","size","exclusive","value","disabled","aria-label","ariaLabel","onChange","_event","next","sx","flexShrink","map","choice","color","px","py","textTransform","labels","PermissionChoiceList","searchId","visible","sections","filter","section","items","length","spacing","onSearchChange","id","type","label","search","event","target","variant","emptyMessage","granted","item","denied","shared","every","changeable","lockedReason","key","component","direction","xs","sm","alignItems","justifyContent","mb","flexWrap","rowGap","groupActions","divider","flexItem","border","borderColor","borderRadius","toggle","span","Boolean","minWidth","description","effective","source","inheritHint","title","displayName"],"mappings":"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"}
|
|
@@ -11,6 +11,11 @@ export interface StatusChipProps {
|
|
|
11
11
|
icon?: ReactElement;
|
|
12
12
|
/** Outlined for a quiet status beside other content; filled to stand out. */
|
|
13
13
|
variant?: 'filled' | 'outlined';
|
|
14
|
+
/**
|
|
15
|
+
* The root element. `span` where the chip sits inside phrasing content,
|
|
16
|
+
* such as a heading or a tab label, where a `div` is not allowed.
|
|
17
|
+
*/
|
|
18
|
+
component?: 'div' | 'span';
|
|
14
19
|
'data-testid'?: string;
|
|
15
20
|
}
|
|
16
21
|
/**
|
|
@@ -30,13 +30,15 @@ const TONE_COLOR = {
|
|
|
30
30
|
* per card, and the same state came out in different colors on different
|
|
31
31
|
* cards; a tone names what the state means and the theme picks the color.
|
|
32
32
|
*/ export function StatusChip(props) {
|
|
33
|
-
const { label, tone = 'neutral', icon, variant = 'filled' } = props;
|
|
33
|
+
const { label, tone = 'neutral', icon, variant = 'filled', component } = props;
|
|
34
34
|
return /*#__PURE__*/ _jsx(Chip, _extends({
|
|
35
35
|
size: "small",
|
|
36
36
|
label: label,
|
|
37
37
|
color: TONE_COLOR[tone],
|
|
38
38
|
variant: variant
|
|
39
|
-
},
|
|
39
|
+
}, component ? {
|
|
40
|
+
component
|
|
41
|
+
} : {}, icon ? {
|
|
40
42
|
icon
|
|
41
43
|
} : {}, {
|
|
42
44
|
"data-testid": props['data-testid']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/status-chip.component.tsx"],"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'use client'\n\nimport Chip, { type ChipProps } from '@mui/material/Chip'\nimport type { ReactElement } from 'react'\n\n/**\n * What a status says about the thing it labels. The five tones are the\n * theme's own palette roles, so a status reads the same in every card.\n */\nexport type StatusTone = 'neutral' | 'info' | 'success' | 'warning' | 'error'\n\nconst TONE_COLOR: Readonly<Record<StatusTone, ChipProps['color']>> = {\n neutral: 'default',\n info: 'info',\n success: 'success',\n warning: 'warning',\n error: 'error',\n}\n\nexport interface StatusChipProps {\n label: string\n tone?: StatusTone\n /** An icon before the label, such as an `MdiIcon`. */\n icon?: ReactElement\n /** Outlined for a quiet status beside other content; filled to stand out. */\n variant?: 'filled' | 'outlined'\n 'data-testid'?: string\n}\n\n/**\n * A record's state as a small chip — On, Connected, Needs attention\n * (AGL-3637). Plugins mapped each status to a hand-picked MUI `Chip` color\n * per card, and the same state came out in different colors on different\n * cards; a tone names what the state means and the theme picks the color.\n */\nexport function StatusChip(props: StatusChipProps) {\n const { label, tone = 'neutral', icon, variant = 'filled' } = props\n return (\n <Chip\n size=\"small\"\n label={label}\n color={TONE_COLOR[tone]}\n variant={variant}\n {...(icon ? { icon } : {})}\n data-testid={props['data-testid']}\n />\n )\n}\nStatusChip.displayName = 'StatusChip'\n\nexport default StatusChip\n"],"names":["Chip","TONE_COLOR","neutral","info","success","warning","error","StatusChip","props","label","tone","icon","variant","size","color","data-testid","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,OAAOA,UAA8B,qBAAoB;AASzD,MAAMC,aAA+D;IACnEC,SAAS;IACTC,MAAM;IACNC,SAAS;IACTC,SAAS;IACTC,OAAO;AACT;
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../libs/shared/ui/jsx/src/lib/components/status-chip.component.tsx"],"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'use client'\n\nimport Chip, { type ChipProps } from '@mui/material/Chip'\nimport type { ReactElement } from 'react'\n\n/**\n * What a status says about the thing it labels. The five tones are the\n * theme's own palette roles, so a status reads the same in every card.\n */\nexport type StatusTone = 'neutral' | 'info' | 'success' | 'warning' | 'error'\n\nconst TONE_COLOR: Readonly<Record<StatusTone, ChipProps['color']>> = {\n neutral: 'default',\n info: 'info',\n success: 'success',\n warning: 'warning',\n error: 'error',\n}\n\nexport interface StatusChipProps {\n label: string\n tone?: StatusTone\n /** An icon before the label, such as an `MdiIcon`. */\n icon?: ReactElement\n /** Outlined for a quiet status beside other content; filled to stand out. */\n variant?: 'filled' | 'outlined'\n /**\n * The root element. `span` where the chip sits inside phrasing content,\n * such as a heading or a tab label, where a `div` is not allowed.\n */\n component?: 'div' | 'span'\n 'data-testid'?: string\n}\n\n/**\n * A record's state as a small chip — On, Connected, Needs attention\n * (AGL-3637). Plugins mapped each status to a hand-picked MUI `Chip` color\n * per card, and the same state came out in different colors on different\n * cards; a tone names what the state means and the theme picks the color.\n */\nexport function StatusChip(props: StatusChipProps) {\n const { label, tone = 'neutral', icon, variant = 'filled', component } = props\n return (\n <Chip\n size=\"small\"\n label={label}\n color={TONE_COLOR[tone]}\n variant={variant}\n {...(component ? { component } : {})}\n {...(icon ? { icon } : {})}\n data-testid={props['data-testid']}\n />\n )\n}\nStatusChip.displayName = 'StatusChip'\n\nexport default StatusChip\n"],"names":["Chip","TONE_COLOR","neutral","info","success","warning","error","StatusChip","props","label","tone","icon","variant","component","size","color","data-testid","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,OAAOA,UAA8B,qBAAoB;AASzD,MAAMC,aAA+D;IACnEC,SAAS;IACTC,MAAM;IACNC,SAAS;IACTC,SAAS;IACTC,OAAO;AACT;AAiBA;;;;;CAKC,GACD,OAAO,SAASC,WAAWC,KAAsB;IAC/C,MAAM,EAAEC,KAAK,EAAEC,OAAO,SAAS,EAAEC,IAAI,EAAEC,UAAU,QAAQ,EAAEC,SAAS,EAAE,GAAGL;IACzE,qBACE,KAACR;QACCc,MAAK;QACLL,OAAOA;QACPM,OAAOd,UAAU,CAACS,KAAK;QACvBE,SAASA;OACJC,YAAY;QAAEA;IAAU,IAAI,CAAC,GAC7BF,OAAO;QAAEA;IAAK,IAAI,CAAC;QACxBK,eAAaR,KAAK,CAAC,cAAc;;AAGvC;AACAD,WAAWU,WAAW,GAAG;AAEzB,eAAeV,WAAU"}
|