@abyss-project/commons-front-core 2.6.2 → 3.0.1

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.
Files changed (120) hide show
  1. package/dist/{CookieConsentSettings.component-BUxrkECh.js → CookieConsentSettings.component-BLgzLD-Z.js} +687 -591
  2. package/dist/components/Avatars/ProjectAvatar/ProjectAvatar.component.d.ts +3 -0
  3. package/dist/components/Avatars/UserAvatar/UserAvatar.component.d.ts +3 -0
  4. package/dist/components/Cards/ProjectCard/ProjectCard.component.d.ts +1 -0
  5. package/dist/components/CommandPalette/AbyssCommandPalette.d.ts +9 -0
  6. package/dist/components/CommandPalette/types.d.ts +63 -0
  7. package/dist/components/CommandPalette/useCommandPaletteHotkey.d.ts +9 -0
  8. package/dist/components/CookieConsent/AbyssCookieConsentProvider.d.ts +9 -1
  9. package/dist/components/CookieConsent/CookieConsentBanner.component.d.ts +0 -1
  10. package/dist/components/CookieConsent/privacy-link.constant.d.ts +25 -0
  11. package/dist/components/Data/AbyssTable/AbyssTable.component.d.ts +16 -2
  12. package/dist/components/Data/AbyssTable/abyss-table.logic.d.ts +72 -0
  13. package/dist/components/Inputs/AbyssNumberField/AbyssNumberField.component.d.ts +18 -0
  14. package/dist/components/Inputs/AbyssNumberField/format.d.ts +28 -0
  15. package/dist/components/Inputs/CloudImport/CloudImport.component.d.ts +1 -0
  16. package/dist/components/Inputs/ColorPalette/ColorPalette.component.d.ts +2 -0
  17. package/dist/components/Inputs/ContextSelector/ContextSelector.component.d.ts +25 -0
  18. package/dist/components/Inputs/DatePeriodPicker/DatePeriodPicker.component.d.ts +32 -0
  19. package/dist/components/Inputs/DatePeriodPicker/date-period-picker.logic.d.ts +54 -0
  20. package/dist/components/Inputs/DatePeriodPicker/date-period-presets.util.d.ts +8 -0
  21. package/dist/components/Inputs/LanguageFlagLabel/LanguageFlagLabel.component.d.ts +13 -0
  22. package/dist/components/Inputs/LanguageFlagLabel/language-flags.d.ts +10 -0
  23. package/dist/components/Inputs/PasswordInput/PasswordInput.component.d.ts +16 -0
  24. package/dist/components/Inputs/ProjectLinkSelector/index.d.ts +1 -1
  25. package/dist/components/Layouts/AbyssBillingPlan/AbyssBillingPlan.component.d.ts +2 -0
  26. package/dist/components/Layouts/AbyssFamilyBanner/AbyssFamilyBanner.component.d.ts +12 -0
  27. package/dist/components/Layouts/AbyssLayoutProvider/index.d.ts +1 -1
  28. package/dist/components/Layouts/AbyssSidebar/index.d.ts +2 -2
  29. package/dist/components/Modals/AbyssModal/AbyssModal.component.d.ts +6 -0
  30. package/dist/components/Modals/QRCodeModal/QRCodeModal.component.d.ts +1 -0
  31. package/dist/components/Modals/UserSettingsModal/UserSettingsModal.component.d.ts +5 -0
  32. package/dist/components/Modals/UserSettingsModal/index.d.ts +1 -1
  33. package/dist/components/PdfEditor/hooks/use-pdf-document.d.ts +12 -0
  34. package/dist/components/PdfEditor/hooks/use-uploaded-docs.d.ts +9 -0
  35. package/dist/components/PdfEditor/operations/actions.d.ts +14 -0
  36. package/dist/components/PdfEditor/operations/compute-page-order.d.ts +11 -0
  37. package/dist/components/PdfEditor/operations/extract.d.ts +5 -0
  38. package/dist/components/PdfEditor/operations/pdf-data-url.d.ts +4 -0
  39. package/dist/components/PdfEditor/operations/rasterize.d.ts +17 -0
  40. package/dist/components/PdfEditor/operations/redact.d.ts +8 -0
  41. package/dist/components/PdfEditor/operations/rotate-coords.d.ts +25 -0
  42. package/dist/components/PdfEditor/signature/SignaturePicker.d.ts +3 -0
  43. package/dist/components/PdfEditor/signature/SignatureSaveButton.d.ts +3 -0
  44. package/dist/components/PdfEditor/signature/resolve-asset.d.ts +17 -0
  45. package/dist/components/PdfEditor/tools/RedactTool.d.ts +6 -0
  46. package/dist/components/PdfEditor/tools/Toolbar.d.ts +9 -0
  47. package/dist/components/PdfEditor/tools/tool-options-ui.d.ts +1 -0
  48. package/dist/components/PdfEditor/types.d.ts +85 -0
  49. package/dist/components/PdfEditor/viewer/PageOverlay.d.ts +10 -0
  50. package/dist/components/PdfEditor/viewer/PdfCanvas.d.ts +1 -0
  51. package/dist/components/PdfEditor/viewer/ViewerControls.d.ts +4 -0
  52. package/dist/components/QuotaGauge/AbyssQuotaGauge.component.d.ts +39 -0
  53. package/dist/components/QuotaGauge/bubble-placement.d.ts +40 -0
  54. package/dist/components/QuotaGauge/gauge-segments.d.ts +56 -0
  55. package/dist/components/QuotaOffer/AbyssQuotaOffer.component.d.ts +60 -0
  56. package/dist/components/QuotaOffer/quota-offer-state.d.ts +64 -0
  57. package/dist/components/QuotaReached/QuotaReachedDialog.component.d.ts +10 -0
  58. package/dist/components/QuotaReached/billing-quota-error.d.ts +7 -0
  59. package/dist/components/QuotaReached/quota-dialog.store.d.ts +10 -0
  60. package/dist/components/QuotaReached/quota-service-meta.d.ts +4 -0
  61. package/dist/components/Support/SupportCategorySelect.component.d.ts +3 -0
  62. package/dist/components/Support/SupportStatusTimeline.component.d.ts +2 -0
  63. package/dist/components/Support/index.d.ts +2 -2
  64. package/dist/components/Support/support-attachment.logic.d.ts +10 -0
  65. package/dist/components/Support/support-author.logic.d.ts +9 -0
  66. package/dist/components/Support/support-create-stepper.logic.d.ts +13 -0
  67. package/dist/components/Support/support-message-input.logic.d.ts +8 -0
  68. package/dist/components/Support/support-status-timeline.logic.d.ts +16 -0
  69. package/dist/components/Support/types.d.ts +55 -0
  70. package/dist/components/Utils/AbyssBackground/AbyssBackground.component.d.ts +3 -0
  71. package/dist/components/Utils/AbyssFamilyMenuSection/AbyssFamilyMenuSection.d.ts +9 -0
  72. package/dist/components/Utils/AbyssLayoutMenu/index.d.ts +1 -1
  73. package/dist/components/Utils/AbyssLayoutNotifications/AbyssLayoutNotifications.component.d.ts +4 -0
  74. package/dist/components/Utils/AbyssLayoutNotifications/index.d.ts +1 -1
  75. package/dist/components/Utils/ImportButton/ImportButton.component.d.ts +4 -0
  76. package/dist/components/Utils/Toast/AbyssToast.component.d.ts +6 -0
  77. package/dist/components/Utils/WaterParticles/WaterParticles.component.d.ts +8 -0
  78. package/dist/cookie-consent.js +1 -1
  79. package/dist/hooks/use-public-users.hook.d.ts +39 -0
  80. package/dist/hooks/use-rich-intl.hook.d.ts +13 -5
  81. package/dist/hooks/use-theme-transition.hook.d.ts +13 -0
  82. package/dist/{index-D_eg_k-b.js → index-13QCr6ei.js} +1 -1
  83. package/dist/{index-uIeKLdVL.js → index-B4s0xpO9.js} +3 -3
  84. package/dist/{index-3FLJ3SfU.js → index-BBH7n9Up.js} +4 -4
  85. package/dist/{index-C_WLdmTl.js → index-BI7XXRdP.js} +3 -3
  86. package/dist/{index-7xq1GVwh.js → index-BbuvDSp0.js} +2 -2
  87. package/dist/{index-XwxG8_UP.js → index-Bhok95RO.js} +2 -2
  88. package/dist/{index-DtSoIucr.js → index-BjbDo-BN.js} +14320 -11454
  89. package/dist/{index-BUU_BiL1.js → index-C2iksP8T.js} +2 -2
  90. package/dist/{index-BLCWSuQw.js → index-CKXa4BvM.js} +2 -2
  91. package/dist/{index-CIrG9_dY.js → index-Ci9slz4U.js} +2 -2
  92. package/dist/{index-C5qcmmpX.js → index-CoGr-vvT.js} +3 -3
  93. package/dist/{index-DcCIQbuV.js → index-Cw4n4Q97.js} +2 -2
  94. package/dist/{index-CtAqjScO.js → index-DKSA-U8A.js} +2 -2
  95. package/dist/{index-DHL1-xk6.js → index-DQ6hF6bv.js} +4 -4
  96. package/dist/{index-Da9DTuJn.js → index-DVDFaXUS.js} +2 -2
  97. package/dist/{index-DjyLPGQg.js → index-Dfs8HrMj.js} +2 -2
  98. package/dist/{index-BErplPpW.js → index-Dn5fa9DE.js} +3 -3
  99. package/dist/{index-Br1U0l5K.js → index-DqW8ipJ0.js} +2 -2
  100. package/dist/{index-DSaH4UP5.js → index-Dt86SHUY.js} +2 -2
  101. package/dist/{index-erzdx1Az.js → index-DucVTPTi.js} +2 -2
  102. package/dist/{index-BcogVLzo.js → index-TJMhsU_S.js} +2 -2
  103. package/dist/{index-CXjoTXWO.js → index-x_CknZJ4.js} +4 -4
  104. package/dist/index.js +2 -2
  105. package/dist/theme/augmentation.d.ts +6 -0
  106. package/dist/theme/index.d.ts +11 -4
  107. package/dist/theme/palettes/common.d.ts +13 -0
  108. package/dist/theme/palettes/dark.d.ts +1 -0
  109. package/dist/theme/palettes/light.d.ts +1 -0
  110. package/dist/theme/tokens/animations.d.ts +3 -0
  111. package/dist/theme/tokens/borders.d.ts +3 -0
  112. package/dist/theme/tokens/colors.d.ts +27 -0
  113. package/dist/theme/tokens/shadows.d.ts +8 -0
  114. package/dist/theme/tokens/transitions.d.ts +4 -0
  115. package/dist/theme/tokens/typography.d.ts +6 -0
  116. package/dist/utils/share-notification.utils.d.ts +9 -0
  117. package/dist/utils/space-display-name.utils.d.ts +8 -0
  118. package/package.json +14 -13
  119. package/tsconfig.json +26 -25
  120. package/vite.config.ts +1 -17
@@ -11,17 +11,27 @@ interface PageOverlayProps {
11
11
  pendingSignature: string | null;
12
12
  pendingText: string | null;
13
13
  pendingApplyAllPages: boolean;
14
+ /** Live virtual page indices (pageOrder) — the targets for "apply to all pages". */
14
15
  pageIndices: number[];
15
16
  dispatch: React.Dispatch<EditorAction>;
16
17
  drawColor?: string;
17
18
  drawStrokeWidth?: number;
19
+ /** New-text styling (existing text keeps its own values). */
18
20
  textColor?: string;
19
21
  textSize?: number;
20
22
  textFamily?: TextFontFamily;
23
+ /** Active shape kind (rect/ellipse/line/arrow) when the shape tool is on. */
21
24
  shapeKind?: ShapeKind;
25
+ /** Fill color for rect/ellipse shapes (hex), or null for outline only. */
22
26
  shapeFill?: string | null;
27
+ /** Highlighter color (hex). */
23
28
  highlightColor?: string;
29
+ /** Render scale (px per PDF point) — driven by the zoom control. */
24
30
  scale?: number;
31
+ /** Total displayed rotation (page intrinsic /Rotate + user delta), clockwise.
32
+ * Annotations are stored in unrotated content space; the overlay maps pointer
33
+ * input back to content space and renders inside a rotated inner layer so the
34
+ * preview matches the baked output. */
25
35
  rotation?: number;
26
36
  }
27
37
  export declare const PageOverlay: React.FC<PageOverlayProps>;
@@ -16,6 +16,7 @@ interface PdfCanvasProps {
16
16
  activePageIndex: number;
17
17
  pageOrder: number[];
18
18
  onPageDimensions?: (pageIndex: number, width: number, height: number, totalRotation: number, pointWidth: number) => void;
19
+ /** Reports the display index of the page currently dominant in the viewport. */
19
20
  onVisiblePageChange?: (displayIndex: number) => void;
20
21
  children?: (virtualIndex: number, displayIndex: number) => React.ReactNode;
21
22
  }
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
2
  interface ViewerControlsProps {
3
+ /** Current zoom as a fraction of the base scale (1 = 100%). */
3
4
  zoom: number;
4
5
  onZoomIn: () => void;
5
6
  onZoomOut: () => void;
@@ -10,7 +11,10 @@ interface ViewerControlsProps {
10
11
  currentPage: number;
11
12
  totalPages: number;
12
13
  onGoToPage: (index: number) => void;
14
+ /** Narrow viewport: dock as a flush full-width bottom bar (no floating pills). */
13
15
  compact?: boolean;
16
+ /** Width (px) of the inline page sidebar, so the floating pills center over the
17
+ * PAGE region rather than the whole area (kept in sync with the placement banner). */
14
18
  sidebarWidth?: number;
15
19
  }
16
20
  export declare const ViewerControls: React.FC<ViewerControlsProps>;
@@ -1,14 +1,53 @@
1
1
  import { default as React } from 'react';
2
2
  import { QuotaGaugeInput } from './gauge-segments';
3
+ /** Un repère sur l'axe : sa valeur, ce qu'il implique, et le raccourci qui permet d'agir. */
3
4
  export interface QuotaMarker {
4
5
  kind: 'threshold' | 'included' | 'ceiling';
5
6
  value: number;
7
+ /** Libellé de l'action, et ce qu'elle déclenche. Sans elle, la bulle informe seulement. */
6
8
  onAction?: () => void;
7
9
  }
8
10
  export interface AbyssQuotaGaugeProps extends QuotaGaugeInput {
9
11
  markers?: QuotaMarker[];
12
+ /** Rend une valeur dans l'unité de la métrique — « 1,5 To », « 12 000 événements ». */
10
13
  formatValue?: (value: number) => string;
14
+ /** Hauteur de la barre. La bulle et les repères s'y adaptent. */
11
15
  height?: number;
16
+ /**
17
+ * Tait la mention « le dépassement n'est pas autorisé » sous l'axe.
18
+ *
19
+ * À poser quand le TEXTE PORTEUR le dit déjà. Dans le bandeau compact du satellite, la phrase
20
+ * apparaissait deux fois à trois lignes d'intervalle : une fois sous la jauge, une fois dans le
21
+ * message d'état. Répétée, elle n'informe plus, elle encombre — et c'est exactement le genre de
22
+ * détail qui fait qu'un écran « n'est pas beau » sans qu'on sache dire pourquoi.
23
+ */
12
24
  hideOverageNote?: boolean;
13
25
  }
26
+ /**
27
+ * LA JAUGE DE QUOTA PARTAGÉE.
28
+ *
29
+ * ═══ POURQUOI ELLE EXISTE ═══
30
+ *
31
+ * Aucune barre de progression partagée n'existait : chaque surface de facturation réimplémentait la
32
+ * sienne, avec ses propres couleurs de seuil. Vérifié — `commons-front-core` ne portait qu'une
33
+ * boîte de dialogue « quota atteint », et quatre écrans du hub avaient chacun leur `LinearProgress`.
34
+ *
35
+ * ═══ IL N'Y A PAS DE LÉGENDE, ET C'EST DÉLIBÉRÉ ═══
36
+ *
37
+ * Chaque SEGMENT porte à la fois sa couleur ET son explication. La solution « remplissage décoratif
38
+ * plus zone de survol invisible » ferait deux sources à garder synchronisées ; un seul nœud ne peut
39
+ * pas dériver. Le survol l'éclaire et fait reculer les autres — le contraste fait la lecture.
40
+ *
41
+ * ═══ UNE BULLE QUI CONTIENT UN BOUTON N'EST PAS UNE BULLE ═══
42
+ *
43
+ * Un pseudo-élément CSS ne se clique pas. Il faut un vrai nœud, survolable, qui reste ouvert quand
44
+ * la souris y entre — et PORTALISÉ, sinon l'`overflow: hidden` de la carte porteuse le rogne.
45
+ *
46
+ * ═══ LE CALCUL N'EST PAS ICI ═══
47
+ *
48
+ * Le placement des bulles et le découpage de l'axe vivent dans deux modules purs, testés sans
49
+ * navigateur sur les quatre largeurs de la spec. Les laisser dans le composant les aurait rendus
50
+ * vérifiables seulement à l'œil — et le premier passage du contrôle signalait quinze défauts sur
51
+ * quinze en mobile, dont aucun n'était visible à la relecture.
52
+ */
14
53
  export declare const AbyssQuotaGauge: React.FC<AbyssQuotaGaugeProps>;
@@ -1,7 +1,47 @@
1
+ /**
2
+ * LE PLACEMENT D'UNE BULLE DE REPÈRE SUR LA JAUGE DE QUOTA.
3
+ *
4
+ * ═══ POURQUOI CE CALCUL EST UNE FONCTION PURE, ET PAS DU CSS ═══
5
+ *
6
+ * Trois pièges, tous rencontrés en MESURANT plutôt qu'en regardant. Le contrôle qui a servi aux
7
+ * maquettes signalait quinze défauts sur quinze en mobile, et aucune relecture ne les aurait vus.
8
+ *
9
+ * 1. UN SEUIL EN POURCENTAGE NE MARCHE PAS. Le point de bascule entre « bulle centrée » et
10
+ * « bulle collée au bord » dépend de la largeur RENDUE, qui change avec l'écran ET avec la
11
+ * langue — un libellé allemand décale le basculement d'un repère qu'un libellé français
12
+ * laissait tenir.
13
+ *
14
+ * 2. `left: 0` SE RÉFÈRE AU PORTEUR, PAS À LA JAUGE. Ancrer sur un bord ne suffit pas : il faut
15
+ * convertir en coordonnées de jauge, sinon la bulle d'un repère à 80 % part 80 % trop à
16
+ * droite.
17
+ *
18
+ * 3. SUR ÉCRAN ÉTROIT LA BULLE EST PLUS LARGE QUE LA JAUGE. Aucune position ne la fait alors
19
+ * tenir : il faut la RÉTRÉCIR d'abord. C'est la ligne `min(...)` ci-dessous, et c'est elle qui
20
+ * règle les quinze défauts mobiles.
21
+ *
22
+ * Sortir ce calcul du composant le rend testable sans navigateur, aux quatre largeurs de la spec,
23
+ * sans monter de DOM ni simuler un survol.
24
+ */
25
+ /** La largeur de confort d'une bulle, en pixels. Au-delà, le texte se met à flotter. */
1
26
  export declare const BUBBLE_MAX_WIDTH = 232;
2
27
  export interface BubblePlacement {
28
+ /** Largeur retenue : la largeur de confort, ou celle de la jauge si elle est plus étroite. */
3
29
  width: number;
30
+ /** Décalage du bord GAUCHE de la bulle, en coordonnées de jauge. */
4
31
  left: number;
32
+ /**
33
+ * Décalage de la flèche À L'INTÉRIEUR de la bulle.
34
+ *
35
+ * Elle reste sous le porteur où que la bulle atterrisse : une flèche figée au centre pointerait
36
+ * dans le vide dès que la bulle est bornée par un bord.
37
+ */
5
38
  arrow: number;
6
39
  }
40
+ /**
41
+ * Place une bulle sous un repère.
42
+ *
43
+ * @param markerCenter position du repère, en pixels depuis le bord gauche de la JAUGE
44
+ * @param gaugeWidth largeur rendue de la jauge, en pixels
45
+ * @param maxWidth largeur de confort de la bulle
46
+ */
7
47
  export declare const placeBubble: (markerCenter: number, gaugeWidth: number, maxWidth?: number) => BubblePlacement;
@@ -1,24 +1,80 @@
1
+ /**
2
+ * LES SEGMENTS D'UNE JAUGE DE QUOTA, ET L'AXE SUR LEQUEL ILS SE POSENT.
3
+ *
4
+ * ═══ L'AXE S'ARRÊTE AU PLAFOND, PAS AU MAXIMUM VENDABLE ═══
5
+ *
6
+ * Porter l'axe jusqu'au maximum libre-service écraserait la zone utile : un compte à 200 Go inclus
7
+ * dont le maximum est 5 To verrait sa limite incluse et son seuil d'alerte confondus sur 4 % de la
8
+ * barre. L'axe s'arrête donc au PLAFOND — le maximum réel du compte —, et le fait qu'il soit
9
+ * relevable devient une affordance plutôt qu'une zone à l'échelle qui mentirait.
10
+ *
11
+ * Sans plafond fixé, l'axe s'arrête à la limite incluse.
12
+ *
13
+ * ═══ POURQUOI CE CALCUL EST PUR ═══
14
+ *
15
+ * Un segment porte à la fois sa couleur ET son explication. La solution « remplissage décoratif
16
+ * plus zone de survol invisible » ferait deux sources à garder synchronisées ; un seul nœud ne peut
17
+ * pas dériver. Encore faut-il que ce nœud sache exactement où il commence et où il finit — d'où ce
18
+ * calcul, testable sans monter de DOM.
19
+ */
20
+ /** Ce qu'un segment raconte. Le nom porte le sens, pas la couleur : le thème décide du rendu. */
1
21
  export declare enum QuotaSegmentKind {
22
+ /** Consommé à l'intérieur de ce que le plan inclut. */
2
23
  USED_INCLUDED = "USED_INCLUDED",
24
+ /** Consommé au-delà de l'inclus — facturé en dépassement. */
3
25
  USED_OVERAGE = "USED_OVERAGE",
26
+ /** Encore inclus, pas encore consommé. */
4
27
  FREE_INCLUDED = "FREE_INCLUDED",
28
+ /** Dépassement encore autorisé avant le plafond. */
5
29
  FREE_OVERAGE = "FREE_OVERAGE"
6
30
  }
7
31
  export interface QuotaSegment {
8
32
  kind: QuotaSegmentKind;
33
+ /** Début et fin en unités de la métrique. */
9
34
  from: number;
10
35
  to: number;
36
+ /** Part de l'axe, entre 0 et 1 — ce que le rendu utilise pour sa largeur. */
11
37
  ratio: number;
12
38
  }
13
39
  export interface QuotaAxis {
40
+ /** Fin de l'axe, en unités de la métrique. */
14
41
  max: number;
15
42
  segments: QuotaSegment[];
43
+ /** `true` quand l'axe s'arrête à l'inclus faute de plafond : le dépassement n'est pas autorisé. */
16
44
  overageDisallowed: boolean;
17
45
  }
18
46
  export interface QuotaGaugeInput {
47
+ /** Consommation courante. */
19
48
  current: number;
49
+ /** Ce que le plan et les modules incluent. `-1` vaut illimité. */
20
50
  includedLimit: number;
51
+ /**
52
+ * Le plafond du compte, au-delà duquel tout est refusé. `null` : aucun plafond posé, donc aucun
53
+ * dépassement autorisé. `-1` : dépassement sans borne.
54
+ */
21
55
  ceiling: number | null;
22
56
  }
57
+ /**
58
+ * Découpe l'axe en segments contigus.
59
+ *
60
+ * ═══ LES TROIS CAS QUI NE SE DEVINENT PAS ═══
61
+ *
62
+ * ILLIMITÉ — une limite à `-1` n'a pas d'axe : une barre de progression vers l'infini est toujours
63
+ * à zéro pour cent, ce qui est vrai et inutile. On rend un axe vide, et le rendu affiche un état
64
+ * plutôt qu'une jauge.
65
+ *
66
+ * DÉPASSEMENT SANS BORNE — le plafond `-1` ne peut pas terminer l'axe. On le termine à la
67
+ * consommation courante quand elle dépasse l'inclus, sinon à l'inclus : l'axe suit alors le client
68
+ * au lieu de lui montrer un infini vide.
69
+ *
70
+ * CONSOMMATION AU-DELÀ DU PLAFOND — elle arrive : un plafond baissé après coup, ou un compteur
71
+ * rattrapé en retard. L'axe s'étend jusqu'à elle, sinon le segment consommé sortirait de la barre.
72
+ */
23
73
  export declare const buildQuotaAxis: ({ current, includedLimit, ceiling, }: QuotaGaugeInput) => QuotaAxis;
74
+ /**
75
+ * La position d'un repère sur l'axe, en part de l'axe entre 0 et 1.
76
+ *
77
+ * Rend `null` quand le repère n'a pas sa place — pas d'axe, ou une valeur au-delà de son bout. Le
78
+ * rendre à 1 le collerait au bord droit et le ferait passer pour un plafond, ce qu'il n'est pas.
79
+ */
24
80
  export declare const markerRatio: (value: number | null, axis: QuotaAxis) => number | null;
@@ -1,23 +1,83 @@
1
1
  import { default as React } from 'react';
2
2
  import { QuotaMarker } from '../QuotaGauge';
3
3
  import { QuotaOfferInput } from './quota-offer-state';
4
+ /** Une branche chiffrée. Le composant ne calcule RIEN : il reçoit le montant déjà fait. */
4
5
  export interface QuotaOfferBranch {
5
6
  kind: 'extension' | 'pack' | 'overage' | 'ceiling' | 'unlock';
7
+ /**
8
+ * Montant formaté, prêt à afficher — « 5,35 € ».
9
+ *
10
+ * `null` veut dire INDISPONIBLE, pas gratuit : le composant l'affiche comme tel plutôt que de
11
+ * l'estimer. Un prix inventé côté client diverge de la facture au premier changement de barème.
12
+ */
6
13
  price: string | null;
14
+ /** Taille du lot, pour l'extension. */
7
15
  lot?: number;
8
16
  onSelect?: () => void;
9
17
  }
10
18
  export interface AbyssQuotaOfferProps extends QuotaOfferInput {
19
+ /** Unité affichée — « Go », « membres ». */
11
20
  unit: string;
21
+ /** La métrique, telle que le contrat d'URL l'attend. */
12
22
  metricKey: string;
13
23
  branches: QuotaOfferBranch[];
14
24
  variant?: 'compact' | 'expanded';
15
25
  markers?: QuotaMarker[];
26
+ /**
27
+ * Rend une valeur dans l'unité de la métrique. Par défaut, `Intl` — jamais `String(v)`, qui
28
+ * affichait « 110000 » là où le client lit « 110 000 ».
29
+ */
16
30
  formatValue?: (value: number) => string;
31
+ /**
32
+ * La RACINE de facturation du hub — pas l'URL complète.
33
+ *
34
+ * LE SATELLITE NE LA CONNAÎT PAS : il la reçoit, comme il reçoit les prix. Embarquer un tunnel
35
+ * d'achat dans un satellite y dupliquerait Stripe, le moyen de paiement et les items
36
+ * d'abonnement — tout ce qui vit dans le hub, neuf fois.
37
+ *
38
+ * Le lien profond est construit ICI, avec la métrique, le geste visé et l'adresse de retour :
39
+ * neuf satellites qui le fabriqueraient chacun de leur côté finiraient par en perdre un morceau.
40
+ */
41
+ /**
42
+ * Le service qui sert cette métrique. Le point d'entrée d'offre en exige le couple complet ; le
43
+ * composant le reçoit du serveur, avec l'offre qu'il affiche.
44
+ */
17
45
  serviceKey: string;
18
46
  billingBaseUrl?: string;
47
+ /**
48
+ * L'organisation dont le quota est affiché, quand il y en a une.
49
+ *
50
+ * Le hub sert la consommation d'une organisation sur une route DISTINCTE, qui porte
51
+ * l'identifiant dans le chemin. Sans lui, un membre d'une organisation atterrit sur la
52
+ * consommation de son compte PERSONNEL : des chiffres réels, mais ceux d'un autre compte que
53
+ * celui qu'il regardait — pire qu'une page d'erreur, qui au moins se voit.
54
+ */
19
55
  organizationId?: string;
56
+ /** Où revenir après le geste. Généralement l'adresse courante du satellite. */
20
57
  returnUrl?: string;
21
58
  onNavigateToBilling?: () => void;
22
59
  }
60
+ /**
61
+ * L'OFFRE DE QUOTA, ET SES HUIT ÉTATS.
62
+ *
63
+ * ═══ CE QU'IL NE FAIT PAS ═══
64
+ *
65
+ * Il ne CALCULE aucun prix et ne DÉRIVE aucun état : les deux arrivent tout faits, l'un du serveur,
66
+ * l'autre d'une fonction pure testée à part. Un `if` enfoui dans le rendu ne se vérifie qu'à l'œil,
67
+ * sur les quelques cas qu'on pense à ouvrir — et se tromper d'état a deux coûts opposés, tous deux
68
+ * chers.
69
+ *
70
+ * ═══ LES DEUX VARIANTS, ET CE QUI LES DISTINGUE VRAIMENT ═══
71
+ *
72
+ * COMPACT vit dans un satellite : une ligne au-dessus du contenu, JAMAIS devant. Son action REDIRIGE
73
+ * vers le hub — le satellite informe et route, il ne vend pas.
74
+ *
75
+ * ÉTENDU vit dans les pages de facturation du hub : la jauge et les branches chiffrées.
76
+ *
77
+ * ═══ AMBRE SE FERME, ROUGE NE SE FERME PAS ═══
78
+ *
79
+ * En approche, le bandeau est informatif et FERMABLE : l'utilisateur travaille, on ne lui bloque pas
80
+ * l'écran. Au refus, l'action vient d'échouer, le bandeau porte la cause et n'est plus fermable —
81
+ * c'est le seul moment où il a le droit d'insister.
82
+ */
23
83
  export declare const AbyssQuotaOffer: React.FC<AbyssQuotaOfferProps>;
@@ -1,22 +1,86 @@
1
+ /**
2
+ * LES HUIT ÉTATS D'UNE OFFRE DE QUOTA, DÉRIVÉS PLUTÔT QUE DÉCIDÉS À L'AFFICHAGE.
3
+ *
4
+ * ═══ POURQUOI CETTE DÉRIVATION EST PURE ═══
5
+ *
6
+ * Se tromper d'état a deux coûts opposés, et tous deux sont chers : proposer un achat à un client
7
+ * SAIN décrédibilise l'alerte quand elle arrive vraiment, et ne rien proposer à un client BLOQUÉ le
8
+ * laisse devant un refus sans issue. Un `if` enfoui dans le rendu ne se vérifie qu'à l'œil, sur les
9
+ * quelques cas qu'on pense à ouvrir.
10
+ *
11
+ * ═══ CE QUE LE COMPOSANT NE FAIT PAS ═══
12
+ *
13
+ * Il ne CALCULE aucun prix. Les montants arrivent déjà chiffrés par le serveur, par la même
14
+ * fonction qui sert l'achat, la réactivation d'un module suspendu et l'aperçu de descente de gamme.
15
+ * Un barème dupliqué côté client dérive au premier changement, et l'écart se voit sur la facture.
16
+ */
17
+ /** Les huit états, dans l'ordre de la spec. */
1
18
  export declare enum QuotaOfferState {
19
+ /** 1 — sous le seuil. AUCUNE action proposée. */
2
20
  HEALTHY = "HEALTHY",
21
+ /** 2 — seuil d'alerte franchi. Mention discrète. */
3
22
  APPROACHING = "APPROACHING",
23
+ /** 3 — limite atteinte, dépassement possible. Les trois branches. */
4
24
  LIMIT_REACHED = "LIMIT_REACHED",
25
+ /** 4 — limite atteinte, dépassement IMPOSSIBLE. Deux branches, la troisième expliquée. */
5
26
  LIMIT_REACHED_NO_OVERAGE = "LIMIT_REACHED_NO_OVERAGE",
27
+ /** 5 — en dépassement. L'économie chiffrée. */
6
28
  IN_OVERAGE = "IN_OVERAGE",
29
+ /** 6 — plafond atteint. Refus dur, deux issues. */
7
30
  CEILING_REACHED = "CEILING_REACHED",
31
+ /** 7 — réglage : pas de jauge, une option. */
8
32
  SETTING = "SETTING",
33
+ /** 8 — extension suspendue parce que le plan la couvre. */
9
34
  SUSPENDED_BY_PLAN = "SUSPENDED_BY_PLAN"
10
35
  }
11
36
  export interface QuotaOfferInput {
12
37
  current: number;
38
+ /** Ce que le plan et les modules incluent. `-1` vaut illimité. */
13
39
  includedLimit: number;
40
+ /** Plafond du compte. `null` : aucun, donc aucun dépassement autorisé. `-1` : sans borne. */
14
41
  ceiling: number | null;
42
+ /** Seuil d'alerte, en part de l'inclus — 0,8 pour 80 %. */
15
43
  alertThreshold: number;
44
+ /** Une métrique de RÉGLAGE ne se consomme pas : elle se débloque. */
16
45
  isSetting: boolean;
46
+ /** Le module qui étend cette métrique est suspendu parce que le plan le couvre désormais. */
17
47
  moduleSuspendedByPlan: boolean;
48
+ /** Taille d'un lot, dans l'unité de la métrique. `null` : aucun module ne vend cette métrique. */
18
49
  lotSize: number | null;
19
50
  }
51
+ /**
52
+ * Décide l'état à afficher.
53
+ *
54
+ * ═══ L'ORDRE DES TESTS EST LA RÈGLE ═══
55
+ *
56
+ * Il ne s'agit pas de style : un client peut être À LA FOIS en dépassement et avec un module
57
+ * suspendu, ou au plafond d'une métrique de réglage. L'ordre dit lequel de ces faits le concerne le
58
+ * plus, et c'est toujours le plus contraignant — celui qui l'empêche d'agir passe avant celui qui
59
+ * lui coûte de l'argent, qui passe avant celui qui l'informe.
60
+ */
20
61
  export declare const deriveQuotaOfferState: ({ current, includedLimit, ceiling, alertThreshold, isSetting, moduleSuspendedByPlan, }: QuotaOfferInput) => QuotaOfferState;
62
+ /**
63
+ * `true` quand l'état autorise une proposition.
64
+ *
65
+ * L'état SAIN et l'état APPROCHE en sont exclus : le premier ne dit rien, le second mentionne sans
66
+ * vendre. Et la SUSPENSION explique, elle ne propose pas — l'option est déjà couverte par le plan.
67
+ */
21
68
  export declare const offersAction: (state: QuotaOfferState) => boolean;
69
+ /**
70
+ * `true` quand il devient MOINS CHER d'acheter un lot que de subir le dépassement.
71
+ *
72
+ * ═══ L'ARITHMÉTIQUE, PARCE QU'ELLE DÉCIDE DU SEUIL ═══
73
+ *
74
+ * Le dépassement coûte le DOUBLE de la tranche d'entrée (`OVERAGE_MULTIPLIER`), et un lot de `N`
75
+ * unités coûte à peu près `N × tranche`. Dépasser de `X` unités coûte donc `2 × X × tranche`, et
76
+ * acheter devient plus avantageux dès que :
77
+ *
78
+ * 2 × X × tranche > N × tranche ⟺ X > N / 2
79
+ *
80
+ * D'où « la moitié d'un lot », qui n'est pas un chiffre rond choisi au hasard mais le point exact
81
+ * où les deux courbes se croisent.
82
+ *
83
+ * Rend `false` quand aucun module ne vend la métrique : il n'y a pas de lot à proposer, et
84
+ * suggérer un achat impossible est pire que de se taire.
85
+ */
22
86
  export declare const shouldSuggestModule: (current: number, includedLimit: number, lotSize: number | null) => boolean;
@@ -1,5 +1,15 @@
1
1
  import { default as React } from 'react';
2
2
  export interface QuotaReachedDialogProps {
3
+ /**
4
+ * Called when the user clicks the upgrade CTA. The host decides where to send
5
+ * them (internal route or the main dashboard billing URL). When omitted, the
6
+ * CTA button is hidden and only an explanatory message + close button show.
7
+ */
3
8
  onUpgrade?: () => void;
4
9
  }
10
+ /**
11
+ * Shared "quota reached" dialog. Triggered imperatively by the billing-quota
12
+ * axios interceptor (see attachQuotaInterceptor) when a satellite blocks a
13
+ * create because the current plan's limit is hit.
14
+ */
5
15
  export declare const QuotaReachedDialog: React.FC<QuotaReachedDialogProps>;
@@ -1,4 +1,11 @@
1
1
  import { AxiosInstance } from 'axios';
2
2
  import { QuotaDialogPayload } from './quota-dialog.store';
3
+ /**
4
+ * Detects a billing-quota block in an axios error and resolves it into the
5
+ * payload the quota dialog needs. Returns null for anything that is not a
6
+ * recognizable quota block. The local `parseQuotaMetric` helper enforces the
7
+ * backend contract (access_not_allowed code + the exact quota message shape) and
8
+ * returns the offending metric.
9
+ */
3
10
  export declare const parseQuotaError: (error: unknown) => QuotaDialogPayload | null;
4
11
  export declare const attachQuotaInterceptor: (instances: AxiosInstance[]) => void;
@@ -1,8 +1,11 @@
1
1
  import { BillingMetric, BillingService } from '@abyss-project/main';
2
2
  import { UseBoundStore, StoreApi } from 'zustand';
3
3
  export interface QuotaDialogPayload {
4
+ /** Metric that hit its ceiling (e.g. TOOLS_BOARD_COUNT). */
4
5
  metric: BillingMetric;
6
+ /** Owning service, resolved from the metric. */
5
7
  service: BillingService;
8
+ /** Raw backend message, kept for debugging / fallback display. */
6
9
  rawMessage?: string;
7
10
  }
8
11
  interface QuotaDialogState {
@@ -11,5 +14,12 @@ interface QuotaDialogState {
11
14
  show: (payload: QuotaDialogPayload) => void;
12
15
  hide: () => void;
13
16
  }
17
+ /**
18
+ * Shared store driving the global "quota reached" dialog across every Abyss
19
+ * front. The billing-quota axios interceptor lives outside the React tree, so
20
+ * it pushes into this store imperatively via
21
+ * `useQuotaDialogStore.getState().show(...)`. A `<QuotaReachedDialog />`
22
+ * mounted at the host's app root subscribes and renders.
23
+ */
14
24
  export declare const useQuotaDialogStore: UseBoundStore<StoreApi<QuotaDialogState>>;
15
25
  export {};
@@ -6,6 +6,10 @@ interface ServiceMeta {
6
6
  icon: React.ReactElement;
7
7
  color: PaletteKey;
8
8
  }
9
+ /**
10
+ * How each billing service is displayed in the shared quota dialog. Mirrors
11
+ * the front-v2 SERVICE_META so the look is consistent across hosts.
12
+ */
9
13
  export declare const QUOTA_SERVICE_META: Record<BillingService, ServiceMeta>;
10
14
  export declare const getQuotaServiceColor: (theme: Theme, service: BillingService) => string;
11
15
  export declare const renderQuotaServiceIcon: (service: BillingService, fontSize: number) => React.ReactElement;
@@ -1,11 +1,14 @@
1
1
  import { default as React } from 'react';
2
2
  import { SupportTicketCategory } from '@abyss-project/main';
3
3
  interface SupportCategorySelectProps {
4
+ /** Single value mode (create form) */
4
5
  value?: SupportTicketCategory | null;
5
6
  onChange?: (value: SupportTicketCategory | null) => void;
7
+ /** Multiple value mode (filter) */
6
8
  multiple?: boolean;
7
9
  multipleValue?: SupportTicketCategory[];
8
10
  onMultipleChange?: (value: SupportTicketCategory[]) => void;
11
+ /** Common props */
9
12
  label?: string;
10
13
  placeholder?: string;
11
14
  size?: 'small' | 'medium';
@@ -2,6 +2,8 @@ import { default as React } from 'react';
2
2
  import { SupportTicketStatus } from '@abyss-project/main';
3
3
  interface SupportStatusTimelineProps {
4
4
  status: SupportTicketStatus;
5
+ /** Exact current-status label, rendered verbatim above the rail so divergent
6
+ * states (waiting/escalated/archived) stay precise. */
5
7
  currentStatusLabel: string;
6
8
  }
7
9
  export declare const SupportStatusTimeline: React.FC<SupportStatusTimelineProps>;
@@ -10,9 +10,9 @@ export { SupportActivityLog } from './SupportActivityLog.component';
10
10
  export { SupportAttachmentsPanel } from './SupportAttachmentsPanel.component';
11
11
  export { SupportSidebar } from './SupportSidebar.component';
12
12
  export { SupportTicketDetail } from './SupportTicketDetail.component';
13
- export { SupportCategoryChip, getCategoryGroup, getCategoryConfig } from './SupportCategoryChip.component';
13
+ export { SupportCategoryChip, getCategoryGroup, getCategoryConfig, } from './SupportCategoryChip.component';
14
14
  export { SupportCategorySelect } from './SupportCategorySelect.component';
15
15
  export { SupportTopBar } from './SupportTopBar.component';
16
16
  export { SupportCategoryGroupCards } from './SupportCategoryGroupCards.component';
17
17
  export { SupportTicketCreateStepper } from './SupportTicketCreateStepper.component';
18
- export { AbyssServiceSelect, AbyssServiceSingleSelect, AbyssServiceChip, SERVICE_CONFIG as ABYSS_SERVICE_CONFIG, getServiceConfig } from './AbyssServiceSelect.component';
18
+ export { AbyssServiceSelect, AbyssServiceSingleSelect, AbyssServiceChip, SERVICE_CONFIG as ABYSS_SERVICE_CONFIG, getServiceConfig, } from './AbyssServiceSelect.component';
@@ -1,2 +1,12 @@
1
+ /**
2
+ * Pure helpers for support ticket attachment presentation. Kept separate from
3
+ * the React component so the "can this be opened inline?" decision is unit
4
+ * testable in the node-env runner.
5
+ */
6
+ /** True when the mime type renders as an image. */
1
7
  export declare const isImageAttachment: (mimeType: string) => boolean;
8
+ /**
9
+ * True when the attachment can be opened in a new browser tab and rendered
10
+ * inline — images and PDFs. Other types only offer download.
11
+ */
2
12
  export declare const isViewableAttachment: (mimeType: string) => boolean;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Resolves the display alias for a support ticket/message author.
3
+ *
4
+ * Never has access to the raw userId — by construction the caller cannot
5
+ * pass a UUID through this function, so it can never leak one. When neither
6
+ * the batched public-user alias nor the entity's own alias is usable
7
+ * (missing, empty, or whitespace-only), it returns `null` so the caller
8
+ * falls back to a translated "unknown user" label instead of the id.
9
+ */
1
10
  export interface AuthorIdentitySource {
2
11
  alias?: string | null;
3
12
  }
@@ -1,2 +1,15 @@
1
+ /**
2
+ * Pure logic for the support create stepper's form-submission guard.
3
+ *
4
+ * The stepper is a single <form>, so an Enter press in a single-line field
5
+ * triggers implicit form submission. Without a guard that would create the
6
+ * ticket immediately, skipping the remaining steps (priority + attachments).
7
+ * The form's onSubmit consults this to decide whether an Enter/submit should
8
+ * actually create the ticket or just advance to the next step.
9
+ */
1
10
  export type SupportCreateSubmitIntent = 'submit' | 'advance';
11
+ /**
12
+ * Decide what a form-submit event means for the create stepper: only the last
13
+ * step actually creates the ticket; any earlier step advances instead.
14
+ */
2
15
  export declare const resolveCreateSubmitIntent: (isLastStep: boolean) => SupportCreateSubmitIntent;
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Decides whether a keydown event on the support message input should
3
+ * trigger sending the message.
4
+ *
5
+ * Plain Enter never sends — it lets the multiline TextField insert a
6
+ * newline naturally. Sending only fires on Enter combined with Ctrl or
7
+ * Cmd (meta), mirroring the common "Ctrl/Cmd+Enter to send" convention.
8
+ */
1
9
  export interface SendOnKeyDownEvent {
2
10
  key: string;
3
11
  ctrlKey: boolean;
@@ -1,9 +1,25 @@
1
1
  import { SupportTicketStatus } from '@abyss-project/main';
2
+ /**
3
+ * Pure lifecycle-timeline logic for a support ticket's status. Kept separate
4
+ * from the React component so the phase mapping and the divergent-state accent
5
+ * can be unit-tested in the node-env test runner (no DOM).
6
+ */
2
7
  export type SupportTimelinePhaseKey = 'open' | 'in-progress' | 'resolved' | 'closed';
8
+ /**
9
+ * The four canonical lifecycle phases, in order. Divergent statuses
10
+ * (WAITING, ESCALATED) collapse onto the "in-progress" phase; ARCHIVED onto
11
+ * "closed". The exact status is surfaced verbatim elsewhere, so collapsing
12
+ * them loses no information.
13
+ */
3
14
  export declare const SUPPORT_TIMELINE_STEPS: ReadonlyArray<{
4
15
  key: SupportTimelinePhaseKey;
5
16
  statuses: readonly SupportTicketStatus[];
6
17
  }>;
18
+ /**
19
+ * Index (0-3) of the active phase for a given status. Unknown/unmapped values
20
+ * fall back to the first phase rather than -1, so the rail always renders.
21
+ */
7
22
  export declare const supportStatusStepIndex: (status: SupportTicketStatus) => number;
23
+ /** Semantic accent kind for the active node, driven by the exact status. */
8
24
  export type SupportTimelineAccentKind = 'error' | 'warning' | 'muted' | 'brand';
9
25
  export declare const supportStatusAccentKind: (status: SupportTicketStatus) => SupportTimelineAccentKind;