@abyss-project/commons-front-core 8.1.0 → 8.3.0
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/README.md +78 -0
- package/catalog/captures-plan.ts +5 -1
- package/catalog/catalog-entries.ts +21 -1
- package/catalog/cloud-picker-fixture.tsx +97 -0
- package/catalog/pages/AccountMenu.tsx +62 -0
- package/catalog/pages/Avatar.tsx +94 -0
- package/catalog/pages/Callout.tsx +67 -0
- package/catalog/pages/CloudImport.tsx +35 -0
- package/catalog/pages/ContextSelector.tsx +103 -0
- package/catalog/pages/CopyField.tsx +29 -0
- package/catalog/pages/DropZone.tsx +37 -0
- package/catalog/pages/FormField.tsx +54 -0
- package/catalog/pages/ImportButton.tsx +45 -0
- package/catalog/pages/ImportFromCloudModal.tsx +33 -0
- package/catalog/pages/Menu.tsx +99 -98
- package/catalog/pages/NotificationsMenu.tsx +116 -0
- package/catalog/pages/NumberField.tsx +46 -0
- package/catalog/pages/QRCodeModal.tsx +26 -0
- package/catalog/pages/SettingsRow.tsx +67 -0
- package/catalog/pages/Tabs.tsx +72 -0
- package/catalog/pages/UsageMeter.tsx +58 -0
- package/catalog/pages/index.ts +34 -2
- package/catalog/specs/captures.spec.ts +7 -0
- package/catalog/specs/write-capture-index.ts +1 -0
- package/dist/{AbyssCookieConsentProvider-BhSzVu8P.js → AbyssCookieConsentProvider-B-PlGbFf.js} +815 -625
- package/dist/{CookieConsentSettings.component-DMEAuCVS.js → CookieConsentSettings.component-DEGCDEJW.js} +1 -1
- package/dist/components/business/CloudImport/CloudImport.d.ts +24 -0
- package/dist/components/business/CloudImport/cloud-import-tree.d.ts +22 -0
- package/dist/components/business/ImportFromCloudModal/ImportFromCloudModal.d.ts +21 -0
- package/dist/components/business/QRCodeModal/QRCodeModal.d.ts +18 -0
- package/dist/components/business/QRCodeModal/QRCodeModal.spec.d.ts +1 -0
- package/dist/components/business/index.d.ts +3 -0
- package/dist/components/data/DataTable/data-table.types.d.ts +10 -0
- package/dist/components/data/UsageMeter/UsageMeter.d.ts +31 -0
- package/dist/components/data/UsageMeter/UsageMeter.spec.d.ts +1 -0
- package/dist/components/data/index.d.ts +1 -0
- package/dist/components/inputs/ContextSelector/ContextSelector.d.ts +60 -0
- package/dist/components/inputs/ContextSelector/ContextSelector.spec.d.ts +1 -0
- package/dist/components/inputs/CopyField/CopyField.d.ts +19 -0
- package/dist/components/inputs/CopyField/CopyField.spec.d.ts +1 -0
- package/dist/components/inputs/DropZone/DropZone.d.ts +30 -0
- package/dist/components/inputs/DropZone/DropZone.spec.d.ts +1 -0
- package/dist/components/inputs/FormField/FormField.d.ts +29 -0
- package/dist/components/inputs/FormField/FormField.spec.d.ts +1 -0
- package/dist/components/inputs/ImportButton/ImportButton.d.ts +33 -0
- package/dist/components/inputs/ImportButton/ImportButton.spec.d.ts +1 -0
- package/dist/components/inputs/NumberField/NumberField.d.ts +21 -0
- package/dist/components/inputs/NumberField/NumberField.spec.d.ts +1 -0
- package/dist/components/inputs/NumberField/number-input.d.ts +13 -0
- package/dist/components/inputs/SettingsRow/SettingsRow.d.ts +16 -0
- package/dist/components/inputs/SettingsRow/SettingsRow.spec.d.ts +1 -0
- package/dist/components/inputs/index.d.ts +7 -0
- package/dist/components/layers/CommandPalette/CommandPalette.d.ts +27 -6
- package/dist/components/layers/CommandPalette/command-registry.d.ts +39 -9
- package/dist/components/layers/Menu/Menu.d.ts +2 -0
- package/dist/components/layers/Modal/Modal.d.ts +2 -1
- package/dist/components/meaning/Avatar/Avatar.d.ts +41 -0
- package/dist/components/meaning/Avatar/Avatar.spec.d.ts +1 -0
- package/dist/components/meaning/index.d.ts +1 -0
- package/dist/components/states/Callout/Callout.d.ts +25 -0
- package/dist/components/states/Callout/Callout.spec.d.ts +1 -0
- package/dist/components/states/PageState/PageState.d.ts +6 -1
- package/dist/components/states/index.d.ts +1 -0
- package/dist/components/structure/AccountMenu/AccountMenu.d.ts +27 -0
- package/dist/components/structure/AccountMenu/AccountMenu.spec.d.ts +1 -0
- package/dist/components/structure/AppShell/AppShell.d.ts +9 -3
- package/dist/components/structure/AppShell/ShellNavigation.d.ts +4 -2
- package/dist/components/structure/AppShell/app-shell.types.d.ts +38 -2
- package/dist/components/structure/NotificationsMenu/NotificationsMenu.d.ts +36 -0
- package/dist/components/structure/NotificationsMenu/NotificationsMenu.spec.d.ts +1 -0
- package/dist/components/structure/PageHeader/PageHeader.d.ts +2 -2
- package/dist/components/structure/Tabs/Tabs.d.ts +34 -0
- package/dist/components/structure/Tabs/Tabs.spec.d.ts +1 -0
- package/dist/components/structure/index.d.ts +3 -0
- package/dist/components/structure/test-support/structure-test-harness.d.ts +6 -0
- package/dist/cookie-consent.js +2 -2
- package/dist/design-theme-CKTz_cOa.js +15490 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-rich-intl.hook.d.ts +190 -0
- package/dist/hooks/use-scroll-overflow-cue.hook.d.ts +9 -0
- package/dist/hooks/use-scroll-overflow-cue.hook.spec.d.ts +1 -0
- package/dist/{index-D5e4uD4k.js → index-7N3J68EI.js} +2 -2
- package/dist/{index-BqIg55B3.js → index-B3rK_-T4.js} +4 -4
- package/dist/{index-6KdfKdSJ.js → index-B6qHo25Z.js} +2 -2
- package/dist/{index-BTjzj7mm.js → index-BMaAO_4e.js} +2 -2
- package/dist/{index-CHGRiRCe.js → index-B_jSh70G.js} +3 -3
- package/dist/{index-BkfBpYKR.js → index-B_yywet5.js} +3 -3
- package/dist/{index-DixNft1u.js → index-Bdtvzv-J.js} +2 -2
- package/dist/{index-ClLoBnCN.js → index-Bh2_8FCK.js} +2 -2
- package/dist/{index-D_GWBYM2.js → index-Bpg9TBMX.js} +1 -1
- package/dist/{index-GoHiFeaw.js → index-Bpnf8xKI.js} +2 -2
- package/dist/{index-bR-mnNUA.js → index-Bw2swxVq.js} +2 -2
- package/dist/{index-LdiTmDFg.js → index-BxxZgBFn.js} +2 -2
- package/dist/{index-ASLTmD1Y.js → index-Ca9tzEsn.js} +2 -2
- package/dist/{index-21vSFz6u.js → index-Csvh-AG6.js} +2 -2
- package/dist/{index-l7FAjaVB.js → index-CwuklsUK.js} +3 -3
- package/dist/{index-Ni4BmFs4.js → index-DFC9xBY9.js} +2 -2
- package/dist/{index-Btnmn1iK.js → index-DfUcsAJv.js} +4 -4
- package/dist/{index-D4Qh2Iww.js → index-DqedXp41.js} +3 -3
- package/dist/{index-BVS73U9E.js → index-DwXNHQIp.js} +4 -4
- package/dist/{index-BtsnuEJC.js → index-_UY_fqvv.js} +28415 -34554
- package/dist/{index-7HAvRXgu.js → index-dVVflNge.js} +2 -2
- package/dist/{index-C92C_oG5.js → index-sEWp0xIC.js} +2 -2
- package/dist/index.js +8273 -5009
- package/dist/legacy/components/QuotaOffer/AbyssQuotaOffer.component.d.ts +1 -1
- package/dist/legacy/components/QuotaOffer/index.d.ts +2 -2
- package/dist/legacy/theme/core-breakpoints-under-legacy-theme.spec.d.ts +1 -0
- package/dist/legacy.js +144 -144
- package/dist/theme/DesignCssVariables.d.ts +11 -0
- package/dist/theme/DesignCssVariables.spec.d.ts +1 -0
- package/dist/theme/components/shared.d.ts +4 -1
- package/dist/theme/css-variables.d.ts +7 -0
- package/dist/theme/design-media.d.ts +26 -0
- package/dist/theme/design-media.spec.d.ts +1 -0
- package/dist/theme/focus-ring.spec.d.ts +1 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/tokens/semantic.d.ts +1 -1
- package/dist/theme/use-design-breakpoint.d.ts +7 -0
- package/dist/translations/en.d.ts +95 -0
- package/dist/translations/fr.d.ts +95 -0
- package/dist/utils/cloud-accept.utils.spec.d.ts +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/quota-offer-state.utils.spec.d.ts +1 -0
- package/package.json +1 -1
- package/test-results/catalog/.last-run.json +4 -0
- package/dist/design-theme-CvLzOz3p.js +0 -9305
- /package/dist/{legacy/components/Inputs/CloudImport/cloud-accept.spec.d.ts → components/business/CloudImport/CloudImport.spec.d.ts} +0 -0
- /package/dist/{legacy/components/QuotaOffer/quota-offer-state.spec.d.ts → components/business/ImportFromCloudModal/ImportFromCloudModal.spec.d.ts} +0 -0
- /package/dist/{legacy/components/Inputs/CloudImport/cloud-accept.d.ts → utils/cloud-accept.utils.d.ts} +0 -0
- /package/dist/{legacy/components/QuotaOffer/quota-offer-state.d.ts → utils/quota-offer-state.utils.d.ts} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DropZone } from '../../src/components/inputs/DropZone/DropZone';
|
|
2
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
3
|
+
import { CATALOG_CLOUD_PICKER } from '../cloud-picker-fixture';
|
|
4
|
+
|
|
5
|
+
const TEN_MIB = 10 * 1024 * 1024;
|
|
6
|
+
|
|
7
|
+
export const DropZonePage = () => {
|
|
8
|
+
const { log } = useEventLog();
|
|
9
|
+
const dropped = (files: File[]) =>
|
|
10
|
+
log(`déposé ${files.map((file) => file.name).join(', ')}`);
|
|
11
|
+
return (
|
|
12
|
+
<Showcase
|
|
13
|
+
family="Saisie"
|
|
14
|
+
name="DropZone"
|
|
15
|
+
description="Zone de dépôt de fichiers : bouton pour parcourir l'appareil, limite de taille, refus expliqués sous la zone, entrée AbyssCloud quand elle est branchée. Sous 768 px, seul le bouton reste."
|
|
16
|
+
>
|
|
17
|
+
<Example title="Une image, avec AbyssCloud" maxWidth={640}>
|
|
18
|
+
<DropZone
|
|
19
|
+
title="Signature"
|
|
20
|
+
onDrop={dropped}
|
|
21
|
+
multiple={false}
|
|
22
|
+
accept={{ 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg'] }}
|
|
23
|
+
maxSize={TEN_MIB}
|
|
24
|
+
cloudImport={{
|
|
25
|
+
...CATALOG_CLOUD_PICKER,
|
|
26
|
+
onImport: (_space, files) =>
|
|
27
|
+
log(`importé ${files.map((file) => file.name).join(', ')}`),
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
</Example>
|
|
31
|
+
<Example title="Plusieurs fichiers, sans AbyssCloud" maxWidth={640}>
|
|
32
|
+
<DropZone onDrop={dropped} maxSize={TEN_MIB} />
|
|
33
|
+
</Example>
|
|
34
|
+
<LastEvent />
|
|
35
|
+
</Showcase>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
3
|
+
import OutlinedInput from '@mui/material/OutlinedInput';
|
|
4
|
+
import Select from '@mui/material/Select';
|
|
5
|
+
import { FormField } from '../../src/components/inputs/FormField/FormField';
|
|
6
|
+
import { Columns, Example, Showcase } from '../frame';
|
|
7
|
+
|
|
8
|
+
export const FormFieldPage = () => {
|
|
9
|
+
const [company, setCompany] = useState('Abyss SAS');
|
|
10
|
+
const [vat, setVat] = useState('FR123');
|
|
11
|
+
const [country, setCountry] = useState('fr');
|
|
12
|
+
return (
|
|
13
|
+
<Showcase
|
|
14
|
+
family="Saisie"
|
|
15
|
+
name="FormField"
|
|
16
|
+
description="Libellé, aide et erreur autour d'un champ MUI : l'id et les aria-describedby sont reliés, l'erreur et l'obligation passent au champ."
|
|
17
|
+
>
|
|
18
|
+
<Example title="Aide et obligation, erreur, liste">
|
|
19
|
+
<Columns>
|
|
20
|
+
<FormField
|
|
21
|
+
label="Raison sociale"
|
|
22
|
+
help="Telle qu'elle figure sur vos factures."
|
|
23
|
+
required
|
|
24
|
+
>
|
|
25
|
+
<OutlinedInput
|
|
26
|
+
value={company}
|
|
27
|
+
onChange={(event) => setCompany(event.target.value)}
|
|
28
|
+
/>
|
|
29
|
+
</FormField>
|
|
30
|
+
<FormField
|
|
31
|
+
label="Numéro de TVA"
|
|
32
|
+
help="FR suivi de 11 chiffres."
|
|
33
|
+
error="Ce numéro n'est pas valide."
|
|
34
|
+
>
|
|
35
|
+
<OutlinedInput
|
|
36
|
+
value={vat}
|
|
37
|
+
onChange={(event) => setVat(event.target.value)}
|
|
38
|
+
/>
|
|
39
|
+
</FormField>
|
|
40
|
+
<FormField label="Pays de facturation">
|
|
41
|
+
<Select
|
|
42
|
+
value={country}
|
|
43
|
+
onChange={(event) => setCountry(event.target.value)}
|
|
44
|
+
>
|
|
45
|
+
<MenuItem value="fr">France</MenuItem>
|
|
46
|
+
<MenuItem value="be">Belgique</MenuItem>
|
|
47
|
+
<MenuItem value="ch">Suisse</MenuItem>
|
|
48
|
+
</Select>
|
|
49
|
+
</FormField>
|
|
50
|
+
</Columns>
|
|
51
|
+
</Example>
|
|
52
|
+
</Showcase>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import Button from '@mui/material/Button';
|
|
2
|
+
import FileUploadOutlinedIcon from '@mui/icons-material/FileUploadOutlined';
|
|
3
|
+
import { ImportButton } from '../../src/components/inputs/ImportButton/ImportButton';
|
|
4
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
5
|
+
import { CATALOG_CLOUD_PICKER } from '../cloud-picker-fixture';
|
|
6
|
+
|
|
7
|
+
export const ImportButtonPage = () => {
|
|
8
|
+
const { log } = useEventLog();
|
|
9
|
+
return (
|
|
10
|
+
<Showcase
|
|
11
|
+
family="Saisie"
|
|
12
|
+
name="ImportButton"
|
|
13
|
+
description="Un déclencheur qui ouvre le menu des sources : l'appareil, un lien (adresse vérifiée avant l'import), AbyssCloud."
|
|
14
|
+
>
|
|
15
|
+
<Example title="Trois sources">
|
|
16
|
+
<ImportButton
|
|
17
|
+
isLoading={false}
|
|
18
|
+
handleFileUpload={async (event) =>
|
|
19
|
+
log(`fichier ${event.target.files?.[0]?.name ?? ''}`)
|
|
20
|
+
}
|
|
21
|
+
handleUploadFromUrl={async (url) => log(`lien ${url}`)}
|
|
22
|
+
accept={['image/*']}
|
|
23
|
+
cloudImport={{
|
|
24
|
+
...CATALOG_CLOUD_PICKER,
|
|
25
|
+
onImport: (_space, files) =>
|
|
26
|
+
log(`importé ${files.map((file) => file.name).join(', ')}`),
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
<Button
|
|
30
|
+
variant="outlined"
|
|
31
|
+
startIcon={<FileUploadOutlinedIcon aria-hidden />}
|
|
32
|
+
>
|
|
33
|
+
Importer une image
|
|
34
|
+
</Button>
|
|
35
|
+
</ImportButton>
|
|
36
|
+
</Example>
|
|
37
|
+
<Example title="L'appareil seulement, import en cours">
|
|
38
|
+
<ImportButton isLoading handleFileUpload={async () => undefined}>
|
|
39
|
+
<Button variant="outlined">Importer</Button>
|
|
40
|
+
</ImportButton>
|
|
41
|
+
</Example>
|
|
42
|
+
<LastEvent />
|
|
43
|
+
</Showcase>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import { ImportFromCloudModal } from '../../src/components/business/ImportFromCloudModal/ImportFromCloudModal';
|
|
4
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
5
|
+
import { CATALOG_CLOUD_PICKER } from '../cloud-picker-fixture';
|
|
6
|
+
|
|
7
|
+
export const ImportFromCloudModalPage = () => {
|
|
8
|
+
const { log } = useEventLog();
|
|
9
|
+
const [open, setOpen] = useState(true);
|
|
10
|
+
return (
|
|
11
|
+
<Showcase
|
|
12
|
+
family="Métier"
|
|
13
|
+
name="ImportFromCloudModal"
|
|
14
|
+
description="Le sélecteur AbyssCloud dans une modale ; une feuille du bas sous 768 px. Importer remet les fichiers à l'hôte et ferme."
|
|
15
|
+
>
|
|
16
|
+
<Example title="Une image">
|
|
17
|
+
<Button variant="outlined" onClick={() => setOpen(true)}>
|
|
18
|
+
Importer depuis AbyssCloud
|
|
19
|
+
</Button>
|
|
20
|
+
</Example>
|
|
21
|
+
<LastEvent />
|
|
22
|
+
<ImportFromCloudModal
|
|
23
|
+
open={open}
|
|
24
|
+
onClose={() => setOpen(false)}
|
|
25
|
+
cloudPicker={CATALOG_CLOUD_PICKER}
|
|
26
|
+
accept={['image/*']}
|
|
27
|
+
onImport={(_space, files) =>
|
|
28
|
+
log(`importé ${files.map((file) => file.name).join(', ')}`)
|
|
29
|
+
}
|
|
30
|
+
/>
|
|
31
|
+
</Showcase>
|
|
32
|
+
);
|
|
33
|
+
};
|
package/catalog/pages/Menu.tsx
CHANGED
|
@@ -1,98 +1,99 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import Button from '@mui/material/Button';
|
|
3
|
-
import ContentCopyOutlined from '@mui/icons-material/ContentCopyOutlined';
|
|
4
|
-
import DeleteOutlineOutlined from '@mui/icons-material/DeleteOutlineOutlined';
|
|
5
|
-
import DriveFileMoveOutlined from '@mui/icons-material/DriveFileMoveOutlined';
|
|
6
|
-
import EditOutlined from '@mui/icons-material/EditOutlined';
|
|
7
|
-
import IosShareOutlined from '@mui/icons-material/IosShareOutlined';
|
|
8
|
-
import LockOutlined from '@mui/icons-material/LockOutlined';
|
|
9
|
-
import MoreHorizRounded from '@mui/icons-material/MoreHorizRounded';
|
|
10
|
-
import {
|
|
11
|
-
Menu,
|
|
12
|
-
MenuItemTone,
|
|
13
|
-
MenuSeparator,
|
|
14
|
-
} from '../../src/components/layers/Menu/Menu';
|
|
15
|
-
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
16
|
-
|
|
17
|
-
export const MenuPage = () => {
|
|
18
|
-
const { log } = useEventLog();
|
|
19
|
-
const trigger = useRef<HTMLButtonElement>(null);
|
|
20
|
-
const [anchor, setAnchor] = useState<HTMLElement | null>(null);
|
|
21
|
-
|
|
22
|
-
// Opened on arrival, so the page shows the menu without a click.
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
setAnchor(trigger.current);
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
const select = (action: string) => () => log(action);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Showcase
|
|
31
|
-
family="Couches"
|
|
32
|
-
name="Menu"
|
|
33
|
-
description="Menu d'actions : icône, raccourci, ton danger, entrées désactivées sautées par les flèches."
|
|
34
|
-
>
|
|
35
|
-
<Example title="Actions d'un fichier">
|
|
36
|
-
<Button
|
|
37
|
-
ref={trigger}
|
|
38
|
-
variant="outlined"
|
|
39
|
-
startIcon={<MoreHorizRounded />}
|
|
40
|
-
onClick={(event) => setAnchor(event.currentTarget)}
|
|
41
|
-
>
|
|
42
|
-
avis-imposition-2026.pdf
|
|
43
|
-
</Button>
|
|
44
|
-
</Example>
|
|
45
|
-
<LastEvent />
|
|
46
|
-
<Menu
|
|
47
|
-
anchorEl={anchor}
|
|
48
|
-
open={anchor !== null}
|
|
49
|
-
onClose={() => setAnchor(null)}
|
|
50
|
-
items={[
|
|
51
|
-
{
|
|
52
|
-
id: 'share',
|
|
53
|
-
label: 'Partager',
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import ContentCopyOutlined from '@mui/icons-material/ContentCopyOutlined';
|
|
4
|
+
import DeleteOutlineOutlined from '@mui/icons-material/DeleteOutlineOutlined';
|
|
5
|
+
import DriveFileMoveOutlined from '@mui/icons-material/DriveFileMoveOutlined';
|
|
6
|
+
import EditOutlined from '@mui/icons-material/EditOutlined';
|
|
7
|
+
import IosShareOutlined from '@mui/icons-material/IosShareOutlined';
|
|
8
|
+
import LockOutlined from '@mui/icons-material/LockOutlined';
|
|
9
|
+
import MoreHorizRounded from '@mui/icons-material/MoreHorizRounded';
|
|
10
|
+
import {
|
|
11
|
+
Menu,
|
|
12
|
+
MenuItemTone,
|
|
13
|
+
MenuSeparator,
|
|
14
|
+
} from '../../src/components/layers/Menu/Menu';
|
|
15
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
16
|
+
|
|
17
|
+
export const MenuPage = () => {
|
|
18
|
+
const { log } = useEventLog();
|
|
19
|
+
const trigger = useRef<HTMLButtonElement>(null);
|
|
20
|
+
const [anchor, setAnchor] = useState<HTMLElement | null>(null);
|
|
21
|
+
|
|
22
|
+
// Opened on arrival, so the page shows the menu without a click.
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setAnchor(trigger.current);
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
const select = (action: string) => () => log(action);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Showcase
|
|
31
|
+
family="Couches"
|
|
32
|
+
name="Menu"
|
|
33
|
+
description="Menu d'actions : icône, description, raccourci, ton danger, entrées désactivées sautées par les flèches."
|
|
34
|
+
>
|
|
35
|
+
<Example title="Actions d'un fichier">
|
|
36
|
+
<Button
|
|
37
|
+
ref={trigger}
|
|
38
|
+
variant="outlined"
|
|
39
|
+
startIcon={<MoreHorizRounded />}
|
|
40
|
+
onClick={(event) => setAnchor(event.currentTarget)}
|
|
41
|
+
>
|
|
42
|
+
avis-imposition-2026.pdf
|
|
43
|
+
</Button>
|
|
44
|
+
</Example>
|
|
45
|
+
<LastEvent />
|
|
46
|
+
<Menu
|
|
47
|
+
anchorEl={anchor}
|
|
48
|
+
open={anchor !== null}
|
|
49
|
+
onClose={() => setAnchor(null)}
|
|
50
|
+
items={[
|
|
51
|
+
{
|
|
52
|
+
id: 'share',
|
|
53
|
+
label: 'Partager',
|
|
54
|
+
description: 'Lien ou invitation par courriel',
|
|
55
|
+
icon: <IosShareOutlined />,
|
|
56
|
+
shortcut: 'Ctrl+Maj+S',
|
|
57
|
+
onSelect: select('partager'),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'rename',
|
|
61
|
+
label: 'Renommer',
|
|
62
|
+
icon: <EditOutlined />,
|
|
63
|
+
shortcut: 'F2',
|
|
64
|
+
onSelect: select('renommer'),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'copy',
|
|
68
|
+
label: 'Copier le lien',
|
|
69
|
+
icon: <ContentCopyOutlined />,
|
|
70
|
+
shortcut: 'Ctrl+L',
|
|
71
|
+
onSelect: select('copier'),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'move',
|
|
75
|
+
label: 'Déplacer',
|
|
76
|
+
icon: <DriveFileMoveOutlined />,
|
|
77
|
+
onSelect: select('déplacer'),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'encrypt',
|
|
81
|
+
label: 'Déjà chiffré',
|
|
82
|
+
icon: <LockOutlined />,
|
|
83
|
+
disabled: true,
|
|
84
|
+
onSelect: select('chiffrer'),
|
|
85
|
+
},
|
|
86
|
+
MenuSeparator.Divider,
|
|
87
|
+
{
|
|
88
|
+
id: 'trash',
|
|
89
|
+
label: 'Mettre à la corbeille',
|
|
90
|
+
icon: <DeleteOutlineOutlined />,
|
|
91
|
+
tone: MenuItemTone.Danger,
|
|
92
|
+
shortcut: 'Suppr',
|
|
93
|
+
onSelect: select('corbeille'),
|
|
94
|
+
},
|
|
95
|
+
]}
|
|
96
|
+
/>
|
|
97
|
+
</Showcase>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import GroupAddOutlined from '@mui/icons-material/GroupAddOutlined';
|
|
4
|
+
import ChatBubbleOutlineOutlined from '@mui/icons-material/ChatBubbleOutlineOutlined';
|
|
5
|
+
import FileDownloadDoneOutlined from '@mui/icons-material/FileDownloadDoneOutlined';
|
|
6
|
+
import { NotificationsMenu } from '../../src/components/structure/NotificationsMenu/NotificationsMenu';
|
|
7
|
+
import type { NotificationItem } from '../../src/components/structure/NotificationsMenu/NotificationsMenu';
|
|
8
|
+
import { Example, LastEvent, Row, Showcase, useEventLog } from '../frame';
|
|
9
|
+
|
|
10
|
+
const MINUTE_MS = 60 * 1000;
|
|
11
|
+
|
|
12
|
+
const initialItems = (): NotificationItem[] => [
|
|
13
|
+
{
|
|
14
|
+
id: 'invite',
|
|
15
|
+
title: 'Ada Lovelace vous invite dans Atelier Nord',
|
|
16
|
+
body: 'Rejoignez l’organisation pour voir ses projets et ses tableaux.',
|
|
17
|
+
createdAt: new Date(Date.now() - 4 * MINUTE_MS),
|
|
18
|
+
read: false,
|
|
19
|
+
icon: <GroupAddOutlined />,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'comment',
|
|
23
|
+
title: 'Nouveau commentaire sur « Roadmap T4 »',
|
|
24
|
+
body: 'Grace : « On décale la refonte du tableau de bord à novembre ? »',
|
|
25
|
+
createdAt: new Date(Date.now() - 70 * MINUTE_MS),
|
|
26
|
+
read: false,
|
|
27
|
+
icon: <ChatBubbleOutlineOutlined />,
|
|
28
|
+
href: '/tableaux/roadmap',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'export',
|
|
32
|
+
title: 'Votre export de relevés est prêt',
|
|
33
|
+
createdAt: new Date(Date.now() - 2 * 24 * 60 * MINUTE_MS),
|
|
34
|
+
read: true,
|
|
35
|
+
icon: <FileDownloadDoneOutlined />,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export const NotificationsMenuPage = () => {
|
|
40
|
+
const { log } = useEventLog();
|
|
41
|
+
const [items, setItems] = useState(initialItems);
|
|
42
|
+
const [sound, setSound] = useState(true);
|
|
43
|
+
const unread = items.filter((item) => !item.read).length;
|
|
44
|
+
const markRead = (id: string) =>
|
|
45
|
+
setItems((current) =>
|
|
46
|
+
current.map((item) => (item.id === id ? { ...item, read: true } : item)),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Showcase
|
|
51
|
+
family="Structure"
|
|
52
|
+
name="NotificationsMenu"
|
|
53
|
+
description="Cloche de la barre du haut : pastille des non lues, panneau (feuille sous 768 px), tout marquer lu, son, préférences, actions par notification."
|
|
54
|
+
>
|
|
55
|
+
<Example title="Barre du haut">
|
|
56
|
+
<Row>
|
|
57
|
+
<NotificationsMenu
|
|
58
|
+
items={items}
|
|
59
|
+
unreadCount={unread}
|
|
60
|
+
loading={false}
|
|
61
|
+
onOpen={() => log('ouvrir')}
|
|
62
|
+
onItemClick={(id) => {
|
|
63
|
+
markRead(id);
|
|
64
|
+
log(`lire ${id}`);
|
|
65
|
+
}}
|
|
66
|
+
onMarkAllRead={() => {
|
|
67
|
+
setItems((current) =>
|
|
68
|
+
current.map((item) => ({ ...item, read: true })),
|
|
69
|
+
);
|
|
70
|
+
log('tout lire');
|
|
71
|
+
}}
|
|
72
|
+
soundEnabled={sound}
|
|
73
|
+
onToggleSound={() => {
|
|
74
|
+
setSound((value) => !value);
|
|
75
|
+
log('son');
|
|
76
|
+
}}
|
|
77
|
+
preferencesHref="/compte/notifications"
|
|
78
|
+
renderItemActions={(item) =>
|
|
79
|
+
item.id === 'invite' && !item.read ? (
|
|
80
|
+
<Button
|
|
81
|
+
size="small"
|
|
82
|
+
variant="outlined"
|
|
83
|
+
onClick={() => {
|
|
84
|
+
markRead(item.id);
|
|
85
|
+
log('accepter');
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
Accepter
|
|
89
|
+
</Button>
|
|
90
|
+
) : null
|
|
91
|
+
}
|
|
92
|
+
/>
|
|
93
|
+
</Row>
|
|
94
|
+
</Example>
|
|
95
|
+
<Example title="Liste vide et premier chargement">
|
|
96
|
+
<Row>
|
|
97
|
+
<NotificationsMenu
|
|
98
|
+
items={[]}
|
|
99
|
+
unreadCount={0}
|
|
100
|
+
loading={false}
|
|
101
|
+
onItemClick={(id) => log(`lire ${id}`)}
|
|
102
|
+
onMarkAllRead={() => log('tout lire')}
|
|
103
|
+
/>
|
|
104
|
+
<NotificationsMenu
|
|
105
|
+
items={[]}
|
|
106
|
+
unreadCount={0}
|
|
107
|
+
loading
|
|
108
|
+
onItemClick={(id) => log(`lire ${id}`)}
|
|
109
|
+
onMarkAllRead={() => log('tout lire')}
|
|
110
|
+
/>
|
|
111
|
+
</Row>
|
|
112
|
+
</Example>
|
|
113
|
+
<LastEvent />
|
|
114
|
+
</Showcase>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { NumberField } from '../../src/components/inputs/NumberField/NumberField';
|
|
3
|
+
import { Columns, Example, Showcase } from '../frame';
|
|
4
|
+
|
|
5
|
+
export const NumberFieldPage = () => {
|
|
6
|
+
const [ceiling, setCeiling] = useState<number | null>(1250.5);
|
|
7
|
+
const [seats, setSeats] = useState<number | null>(12);
|
|
8
|
+
const [empty, setEmpty] = useState<number | null>(null);
|
|
9
|
+
return (
|
|
10
|
+
<Showcase
|
|
11
|
+
family="Saisie"
|
|
12
|
+
name="NumberField"
|
|
13
|
+
description="Nombre saisi et affiché avec les séparateurs de la langue ; « , » ou « . » lus comme marque décimale, borné et arrondi en sortie du champ."
|
|
14
|
+
>
|
|
15
|
+
<Example title="Montant, quantité, champ vide et désactivé">
|
|
16
|
+
<Columns>
|
|
17
|
+
<NumberField
|
|
18
|
+
label="Plafond mensuel"
|
|
19
|
+
value={ceiling}
|
|
20
|
+
onChange={setCeiling}
|
|
21
|
+
decimals={2}
|
|
22
|
+
adornment="€"
|
|
23
|
+
/>
|
|
24
|
+
<NumberField
|
|
25
|
+
label="Sièges"
|
|
26
|
+
value={seats}
|
|
27
|
+
onChange={setSeats}
|
|
28
|
+
min={1}
|
|
29
|
+
/>
|
|
30
|
+
<NumberField
|
|
31
|
+
label="Stockage supplémentaire"
|
|
32
|
+
value={empty}
|
|
33
|
+
onChange={setEmpty}
|
|
34
|
+
adornment="Go"
|
|
35
|
+
/>
|
|
36
|
+
<NumberField
|
|
37
|
+
label="Crédits offerts"
|
|
38
|
+
value={500}
|
|
39
|
+
onChange={() => undefined}
|
|
40
|
+
disabled
|
|
41
|
+
/>
|
|
42
|
+
</Columns>
|
|
43
|
+
</Example>
|
|
44
|
+
</Showcase>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import { QRCodeModal } from '../../src/components/business/QRCodeModal/QRCodeModal';
|
|
4
|
+
import { Example, Showcase } from '../frame';
|
|
5
|
+
|
|
6
|
+
export const QRCodeModalPage = () => {
|
|
7
|
+
const [open, setOpen] = useState(true);
|
|
8
|
+
return (
|
|
9
|
+
<Showcase
|
|
10
|
+
family="Métier"
|
|
11
|
+
name="QRCodeModal"
|
|
12
|
+
description="Un lien en QR code, toujours sur une page claire (jeton paper) pour rester lisible par un appareil photo ; le lien à copier et « Partager »."
|
|
13
|
+
>
|
|
14
|
+
<Example title="Lien de parrainage">
|
|
15
|
+
<Button variant="outlined" onClick={() => setOpen(true)}>
|
|
16
|
+
Afficher le QR code
|
|
17
|
+
</Button>
|
|
18
|
+
</Example>
|
|
19
|
+
<QRCodeModal
|
|
20
|
+
open={open}
|
|
21
|
+
onClose={() => setOpen(false)}
|
|
22
|
+
url="https://abyss-project.fr/auth/register?sponsorship=7f3a9c2e"
|
|
23
|
+
/>
|
|
24
|
+
</Showcase>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
4
|
+
import Select from '@mui/material/Select';
|
|
5
|
+
import Switch from '@mui/material/Switch';
|
|
6
|
+
import { SettingsRow } from '../../src/components/inputs/SettingsRow/SettingsRow';
|
|
7
|
+
import { Surface } from '../../src/components/structure/Surface/Surface';
|
|
8
|
+
import { Example, LastEvent, Showcase, useEventLog } from '../frame';
|
|
9
|
+
|
|
10
|
+
export const SettingsRowPage = () => {
|
|
11
|
+
const { log } = useEventLog();
|
|
12
|
+
const [renew, setRenew] = useState(true);
|
|
13
|
+
const [language, setLanguage] = useState('fr');
|
|
14
|
+
return (
|
|
15
|
+
<Showcase
|
|
16
|
+
family="Saisie"
|
|
17
|
+
name="SettingsRow"
|
|
18
|
+
description="Un réglage : libellé et description à gauche, contrôle à droite, lignes séparées d'un filet ; le contrôle passe sous le texte sous 768 px."
|
|
19
|
+
>
|
|
20
|
+
<Example title="Réglages de l'abonnement, dans une surface">
|
|
21
|
+
<Surface padding={4}>
|
|
22
|
+
<SettingsRow
|
|
23
|
+
label="Renouvellement automatique"
|
|
24
|
+
description="Votre abonnement est reconduit à chaque échéance, au tarif en vigueur."
|
|
25
|
+
htmlFor="catalog-auto-renew"
|
|
26
|
+
control={
|
|
27
|
+
<Switch
|
|
28
|
+
id="catalog-auto-renew"
|
|
29
|
+
checked={renew}
|
|
30
|
+
onChange={(event) => setRenew(event.target.checked)}
|
|
31
|
+
/>
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
<SettingsRow
|
|
35
|
+
label="Langue des factures"
|
|
36
|
+
description="Les prochaines factures seront émises dans cette langue."
|
|
37
|
+
control={
|
|
38
|
+
<Select
|
|
39
|
+
size="small"
|
|
40
|
+
value={language}
|
|
41
|
+
inputProps={{ 'aria-label': 'Langue des factures' }}
|
|
42
|
+
onChange={(event) => setLanguage(event.target.value)}
|
|
43
|
+
>
|
|
44
|
+
<MenuItem value="fr">Français</MenuItem>
|
|
45
|
+
<MenuItem value="en">English</MenuItem>
|
|
46
|
+
</Select>
|
|
47
|
+
}
|
|
48
|
+
/>
|
|
49
|
+
<SettingsRow
|
|
50
|
+
label="Résilier l'abonnement"
|
|
51
|
+
description="Vous gardez l'accès jusqu'à la fin de la période payée."
|
|
52
|
+
control={
|
|
53
|
+
<Button
|
|
54
|
+
variant="outlined"
|
|
55
|
+
color="error"
|
|
56
|
+
onClick={() => log('résilier')}
|
|
57
|
+
>
|
|
58
|
+
Résilier
|
|
59
|
+
</Button>
|
|
60
|
+
}
|
|
61
|
+
/>
|
|
62
|
+
</Surface>
|
|
63
|
+
</Example>
|
|
64
|
+
<LastEvent />
|
|
65
|
+
</Showcase>
|
|
66
|
+
);
|
|
67
|
+
};
|