@egen-civitas/esm-extensions 1.5.0 → 2.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @egen-civitas/esm-extensions
2
2
 
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8a39e13: Rails et zones ouverts aux apps distantes/fédérées : `ToolWindowMeta.iconUrl` (icône personnalisée sûre, rendue en masque monochrome), `getToolWindowMetaProblems` + avertissement précis à l'enregistrement quand une `meta` de rail est invalide (plus d'entrée ignorée en silence), `registerToolWindow` (déclaration par le code, sans `routes.json`), `openToolWindow` (ouverture sans bascule). Guide : `packages/framework/esm-extensions/TOOL-WINDOWS.md`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [159db44]
12
+ - @egen-civitas/esm-api@2.0.0
13
+ - @egen-civitas/esm-config@2.0.0
14
+ - @egen-civitas/esm-utils@2.0.0
15
+ - @egen-civitas/esm-globals@2.0.0
16
+ - @egen-civitas/esm-translations@1.0.3
17
+ - @egen-civitas/esm-state@1.0.3
18
+ - @egen-civitas/esm-feature-flags@1.0.2
19
+
20
+ ## 2.0.0
21
+
22
+ ### Major Changes
23
+
24
+ - b8a56e7: Suppression complète de l'ancienne barre latérale (sidebar) : plus aucune app ne peut la monter. La navigation passe par les rails et zones du shell (`shell-rail-left-slot`, `shell-rail-bottom-slot`, `shell-rail-right-slot`) et la TopBar niveau 2 (`topbar-level2-nav`).
25
+
26
+ Retirés : `LeftNavMenu`, `setLeftNav`, `unsetLeftNav`, `SetLeftNavParams`, `LeftNavStore`, `useLeftNav`, `useLeftNavStore`, `DashboardExtension`, `createDashboard` (lien de sidebar), la variable `--egen-sidenav-width`, les styles `.cds--side-nav*` / `.active-left-nav-link`, la clé de traduction `leftNavigation` et les alias `side-nav` / `sidenav` de `esm-ai-tools`.
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [b8a56e7]
31
+ - @egen-civitas/esm-translations@1.0.2
32
+
3
33
  ## 1.5.0
4
34
 
5
35
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export * from './extensions.js';
2
2
  export * from './helpers.js';
3
- export * from './left-nav.js';
4
3
  export * from './nav-entry.js';
5
4
  export * from './tool-window.js';
5
+ export * from './tool-window-registration.js';
6
6
  export * from './nav-behavior.js';
7
7
  export * from './modals.js';
8
8
  export * from './workspaces.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  export * from "./extensions.js";
2
2
  export * from "./helpers.js";
3
- export * from "./left-nav.js";
4
3
  export * from "./nav-entry.js";
5
4
  export * from "./tool-window.js";
5
+ export * from "./tool-window-registration.js";
6
6
  export * from "./nav-behavior.js";
7
7
  export * from "./modals.js";
8
8
  export * from "./workspaces.js";
package/dist/public.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export { getExtensionNameFromId, registerExtension, attach, detach, detachAll, getAssignedExtensions, registerExtensionSlot, } from './extensions.js';
2
- export { type LeftNavStore, setLeftNav, unsetLeftNav, type SetLeftNavParams } from './left-nav.js';
3
2
  export { type CancelLoading, renderExtension } from './render.js';
4
3
  export { type ExtensionMeta, type ExtensionRegistration, type ExtensionStore, type AssignedExtension, type ConnectedExtension, type ExtensionSlotState, getExtensionStore, } from './store.js';
5
4
  export { type WorkspaceRegistration } from './workspaces.js';
6
5
  export { type ExtensionData, type ComponentConfig } from './types.js';
7
6
  export { TOPBAR_LEVEL2_NAV_SLOT, NAV_ALL_WORKSPACES, type NavEntryMeta, isNavEntryMeta, isNavEntryInWorkspace, } from './nav-entry.js';
8
- export { SHELL_RAIL_LEFT_SLOT, SHELL_RAIL_BOTTOM_SLOT, SHELL_RAIL_RIGHT_SLOT, TOOL_WINDOW_SLOTS, type ToolWindowAnchor, type ToolWindowMeta, isToolWindowMeta, } from './tool-window.js';
7
+ export { SHELL_RAIL_LEFT_SLOT, SHELL_RAIL_BOTTOM_SLOT, SHELL_RAIL_RIGHT_SLOT, TOOL_WINDOW_SLOTS, type ToolWindowAnchor, type ToolWindowMeta, isToolWindowMeta, isToolWindowSlot, isSafeToolWindowIconUrl, getToolWindowMetaProblems, } from './tool-window.js';
8
+ export { registerToolWindow, type ToolWindowRegistration } from './tool-window-registration.js';
9
9
  export { type NavBehavior, type NavBehaviorTarget, type NavSelectContext, registerNavBehavior, getNavBehavior, } from './nav-behavior.js';
10
10
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../src/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,KAAK,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,YAAY,EACjB,cAAc,EACd,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,cAAc,GACf,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../src/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,KAAK,YAAY,EACjB,cAAc,EACd,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAChG,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,cAAc,GACf,MAAM,mBAAmB,CAAC"}
package/dist/public.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { getExtensionNameFromId, registerExtension, attach, detach, detachAll, getAssignedExtensions, registerExtensionSlot } from "./extensions.js";
2
- export { setLeftNav, unsetLeftNav } from "./left-nav.js";
3
2
  export { renderExtension } from "./render.js";
4
3
  export { getExtensionStore } from "./store.js";
5
4
  export { TOPBAR_LEVEL2_NAV_SLOT, NAV_ALL_WORKSPACES, isNavEntryMeta, isNavEntryInWorkspace } from "./nav-entry.js";
6
- export { SHELL_RAIL_LEFT_SLOT, SHELL_RAIL_BOTTOM_SLOT, SHELL_RAIL_RIGHT_SLOT, TOOL_WINDOW_SLOTS, isToolWindowMeta } from "./tool-window.js";
5
+ export { SHELL_RAIL_LEFT_SLOT, SHELL_RAIL_BOTTOM_SLOT, SHELL_RAIL_RIGHT_SLOT, TOOL_WINDOW_SLOTS, isToolWindowMeta, isToolWindowSlot, isSafeToolWindowIconUrl, getToolWindowMetaProblems } from "./tool-window.js";
6
+ export { registerToolWindow } from "./tool-window-registration.js";
7
7
  export { registerNavBehavior, getNavBehavior } from "./nav-behavior.js";
@@ -0,0 +1,24 @@
1
+ import type { ExtensionRegistration } from './store.js';
2
+ import { type ToolWindowAnchor, type ToolWindowMeta } from './tool-window.js';
3
+ export interface ToolWindowRegistration {
4
+ /** Nom du module (de l'app) qui porte la fenêtre : celui de l'importmap / de la fédération. */
5
+ moduleName: string;
6
+ /** Identifiant unique de la fenêtre d'outils (nom de l'extension). */
7
+ name: string;
8
+ /** Zone dans laquelle le contenu s'ouvre ; détermine le rail (voir `ToolWindowMeta.rail` pour le bas). */
9
+ anchor: ToolWindowAnchor;
10
+ /** Bouton du rail + titre de la zone. */
11
+ meta: ToolWindowMeta;
12
+ /** Chargement du contenu (cycles de vie single-spa), appelé quand la zone s'ouvre. */
13
+ load: ExtensionRegistration['load'];
14
+ privileges?: ExtensionRegistration['privileges'];
15
+ featureFlag?: string;
16
+ displayExpression?: string;
17
+ }
18
+ /**
19
+ * Déclare une fenêtre d'outils par le code, sans `routes.json` : pour une app fédérée ou open source
20
+ * qui s'intègre au shell depuis son point d'entrée. Équivalent exact d'une extension `routes.json` posée
21
+ * sur le slot de rail de la zone. Retourne `false` (et avertit) si la `meta` est invalide.
22
+ */
23
+ export declare function registerToolWindow(registration: ToolWindowRegistration): boolean;
24
+ //# sourceMappingURL=tool-window-registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-window-registration.d.ts","sourceRoot":"","sources":["../src/tool-window-registration.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,sBAAsB;IACrC,+FAA+F;IAC/F,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,MAAM,EAAE,gBAAgB,CAAC;IACzB,yCAAyC;IACzC,IAAI,EAAE,cAAc,CAAC;IACrB,sFAAsF;IACtF,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAC;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,sBAAsB,GAAG,OAAO,CAwBhF"}
@@ -0,0 +1,27 @@
1
+ /** @module @category Extension */ import { attach, registerExtension } from "./extensions.js";
2
+ import { getToolWindowMetaProblems, TOOL_WINDOW_SLOTS } from "./tool-window.js";
3
+ /**
4
+ * Déclare une fenêtre d'outils par le code, sans `routes.json` : pour une app fédérée ou open source
5
+ * qui s'intègre au shell depuis son point d'entrée. Équivalent exact d'une extension `routes.json` posée
6
+ * sur le slot de rail de la zone. Retourne `false` (et avertit) si la `meta` est invalide.
7
+ */ export function registerToolWindow(registration) {
8
+ const { moduleName, name, anchor, meta, load, privileges, featureFlag, displayExpression } = registration;
9
+ const problems = getToolWindowMetaProblems(meta);
10
+ if (problems.length > 0 || !TOOL_WINDOW_SLOTS[anchor]) {
11
+ console.warn(`[workbench] La fenêtre d'outils « ${name} » de ${moduleName} n'est pas enregistrée : ${problems.join(' ; ') || `zone inconnue « ${String(anchor)} »`}.`);
12
+ return false;
13
+ }
14
+ registerExtension({
15
+ name,
16
+ moduleName,
17
+ load,
18
+ meta,
19
+ privileges,
20
+ featureFlag,
21
+ displayExpression,
22
+ online: true,
23
+ offline: false
24
+ });
25
+ attach(TOOL_WINDOW_SLOTS[anchor], name);
26
+ return true;
27
+ }
@@ -35,6 +35,13 @@ export interface ToolWindowMeta {
35
35
  titleKey?: string;
36
36
  /** Nom d'icône lucide (ex. `Users`), résolu par le shell dans une liste blanche. */
37
37
  icon?: string;
38
+ /**
39
+ * Icône personnalisée (apps distantes/fédérées qui ne trouvent pas leur bonheur dans la liste
40
+ * blanche) : URL `https://…`, chemin absolu `/…` ou `data:image/svg+xml|png|webp…`. Affichée comme un
41
+ * masque monochrome (elle prend la couleur du rail) : fournir une icône d'une seule teinte. Prioritaire
42
+ * sur `icon`. Jamais injectée comme HTML : aucun script ne peut s'exécuter.
43
+ */
44
+ iconUrl?: string;
38
45
  /** Ordre d'affichage dans le rail (croissant) ; défaut : ordre du slot. */
39
46
  order?: number;
40
47
  /**
@@ -50,6 +57,16 @@ export interface ToolWindowMeta {
50
57
  */
51
58
  rail?: 'left' | 'right';
52
59
  }
60
+ /** Vrai si `url` est une URL d'icône autorisée (`ToolWindowMeta.iconUrl`). */
61
+ export declare function isSafeToolWindowIconUrl(url: unknown): url is string;
62
+ /**
63
+ * Liste précise des problèmes d'une `meta` de fenêtre d'outils (vide = valide). Sert aux messages
64
+ * d'avertissement à l'enregistrement : une entrée invalide n'apparaît pas dans les rails, et le dire
65
+ * clairement évite de chercher pourquoi à l'intégration d'une app distante.
66
+ */
67
+ export declare function getToolWindowMetaProblems(meta: unknown): string[];
53
68
  /** Valide une `meta` d'extension : vrai si c'est une `ToolWindowMeta` exploitable. */
54
69
  export declare function isToolWindowMeta(meta: unknown): meta is ToolWindowMeta;
70
+ /** Vrai si `slot` est l'un des slots de rail du shell. */
71
+ export declare function isToolWindowSlot(slot: string): boolean;
55
72
  //# sourceMappingURL=tool-window.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-window.d.ts","sourceRoot":"","sources":["../src/tool-window.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAIxE,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAUtE"}
1
+ {"version":3,"file":"tool-window.d.ts","sourceRoot":"","sources":["../src/tool-window.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAElC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE3D,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAIxE,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAGnE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAcjE;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,cAAc,CAEtE;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD"}
@@ -26,14 +26,32 @@ export const SHELL_RAIL_RIGHT_SLOT = 'shell-rail-right-slot';
26
26
  bottom: SHELL_RAIL_BOTTOM_SLOT,
27
27
  right: SHELL_RAIL_RIGHT_SLOT
28
28
  };
29
- /** Valide une `meta` d'extension : vrai si c'est une `ToolWindowMeta` exploitable. */ export function isToolWindowMeta(meta) {
30
- if (!meta || typeof meta !== 'object') return false;
29
+ /** Vrai si `url` est une URL d'icône autorisée (`ToolWindowMeta.iconUrl`). */ export function isSafeToolWindowIconUrl(url) {
30
+ if (typeof url !== 'string' || url.length === 0) return false;
31
+ return /^(https:\/\/|\/(?!\/)|data:image\/(svg\+xml|png|webp|gif|jpeg)[;,])/i.test(url);
32
+ }
33
+ /**
34
+ * Liste précise des problèmes d'une `meta` de fenêtre d'outils (vide = valide). Sert aux messages
35
+ * d'avertissement à l'enregistrement : une entrée invalide n'apparaît pas dans les rails, et le dire
36
+ * clairement évite de chercher pourquoi à l'intégration d'une app distante.
37
+ */ export function getToolWindowMetaProblems(meta) {
38
+ if (!meta || typeof meta !== 'object') return [
39
+ '`meta` est absente : ajouter au moins { "title": "…" }'
40
+ ];
31
41
  const m = meta;
32
- if (typeof m.title !== 'string' || m.title.length === 0) return false;
33
- if (m.titleKey !== undefined && typeof m.titleKey !== 'string') return false;
34
- if (m.icon !== undefined && typeof m.icon !== 'string') return false;
35
- if (m.order !== undefined && (typeof m.order !== 'number' || !Number.isFinite(m.order))) return false;
36
- if (m.global !== undefined && typeof m.global !== 'boolean') return false;
37
- if (m.rail !== undefined && m.rail !== 'left' && m.rail !== 'right') return false;
38
- return true;
42
+ const problems = [];
43
+ if (typeof m.title !== 'string' || m.title.length === 0) problems.push('`title` doit être une chaîne non vide');
44
+ if (m.titleKey !== undefined && typeof m.titleKey !== 'string') problems.push('`titleKey` doit être une chaîne');
45
+ if (m.icon !== undefined && typeof m.icon !== 'string') problems.push('`icon` doit être une chaîne');
46
+ if (m.iconUrl !== undefined && !isSafeToolWindowIconUrl(m.iconUrl)) problems.push('`iconUrl` doit commencer par https://, / ou data:image/(svg+xml|png|webp|gif|jpeg)');
47
+ if (m.order !== undefined && (typeof m.order !== 'number' || !Number.isFinite(m.order))) problems.push('`order` doit être un nombre fini');
48
+ if (m.global !== undefined && typeof m.global !== 'boolean') problems.push('`global` doit être un booléen');
49
+ if (m.rail !== undefined && m.rail !== 'left' && m.rail !== 'right') problems.push('`rail` vaut "left" ou "right"');
50
+ return problems;
51
+ }
52
+ /** Valide une `meta` d'extension : vrai si c'est une `ToolWindowMeta` exploitable. */ export function isToolWindowMeta(meta) {
53
+ return getToolWindowMetaProblems(meta).length === 0;
54
+ }
55
+ /** Vrai si `slot` est l'un des slots de rail du shell. */ export function isToolWindowSlot(slot) {
56
+ return Object.values(TOOL_WINDOW_SLOTS).includes(slot);
39
57
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egen-civitas/esm-extensions",
3
- "version": "1.5.0",
3
+ "version": "2.1.0",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Coordinates extensions and extension points in the Egen Frontend",
6
6
  "type": "module",
@@ -63,26 +63,26 @@
63
63
  "lodash-es": "^4.17.21"
64
64
  },
65
65
  "peerDependencies": {
66
- "@egen-civitas/esm-api": "^1.1.1",
67
- "@egen-civitas/esm-config": "^1.0.0",
66
+ "@egen-civitas/esm-api": "^2.0.0",
67
+ "@egen-civitas/esm-config": "^2.0.0",
68
68
  "@egen-civitas/esm-expression-evaluator": "^1.0.0",
69
- "@egen-civitas/esm-feature-flags": "^1.0.0",
70
- "@egen-civitas/esm-globals": "^1.0.3",
71
- "@egen-civitas/esm-state": "^1.0.0",
72
- "@egen-civitas/esm-translations": "^1.0.0",
73
- "@egen-civitas/esm-utils": "^1.0.0",
69
+ "@egen-civitas/esm-feature-flags": "^1.0.2",
70
+ "@egen-civitas/esm-globals": "^2.0.0",
71
+ "@egen-civitas/esm-state": "^1.0.3",
72
+ "@egen-civitas/esm-translations": "^1.0.3",
73
+ "@egen-civitas/esm-utils": "^2.0.0",
74
74
  "react": "18.x",
75
75
  "single-spa": "6.x"
76
76
  },
77
77
  "devDependencies": {
78
- "@egen-civitas/esm-api": "^1.1.1",
79
- "@egen-civitas/esm-config": "^1.0.0",
78
+ "@egen-civitas/esm-api": "^2.0.0",
79
+ "@egen-civitas/esm-config": "^2.0.0",
80
80
  "@egen-civitas/esm-expression-evaluator": "^1.0.0",
81
- "@egen-civitas/esm-feature-flags": "^1.0.0",
82
- "@egen-civitas/esm-globals": "^1.0.3",
83
- "@egen-civitas/esm-state": "^1.0.0",
84
- "@egen-civitas/esm-translations": "^1.0.0",
85
- "@egen-civitas/esm-utils": "^1.0.0",
81
+ "@egen-civitas/esm-feature-flags": "^1.0.2",
82
+ "@egen-civitas/esm-globals": "^2.0.0",
83
+ "@egen-civitas/esm-state": "^1.0.3",
84
+ "@egen-civitas/esm-translations": "^1.0.3",
85
+ "@egen-civitas/esm-utils": "^2.0.0",
86
86
  "@swc/cli": "0.8.1",
87
87
  "@swc/core": "1.15.21",
88
88
  "@vitest/coverage-v8": "^4.1.2",
@@ -1,38 +0,0 @@
1
- import { type ComponentConfig } from './types.js';
2
- import { type ExtensionSlotState } from './store.js';
3
- type LeftNavMode = 'normal' | 'collapsed' | 'hidden';
4
- export interface LeftNavStore {
5
- slotName: string | null;
6
- basePath: string;
7
- mode: LeftNavMode;
8
- componentContext?: ComponentConfig;
9
- state?: ExtensionSlotState;
10
- }
11
- /** @internal */
12
- export declare const leftNavStore: import("zustand").StoreApi<LeftNavStore>;
13
- export interface SetLeftNavParams {
14
- name: string;
15
- basePath: string;
16
- /**
17
- * In normal mode, the left nav is shown in desktop mode, and collapse into hamburger menu button in tablet mode
18
- * In collapsed mode, the left nav is always collapsed, regardless of desktop / tablet mode.
19
- * In hidden mode, the left nav is not shown at all.
20
- */
21
- mode?: LeftNavMode;
22
- componentContext?: ComponentConfig;
23
- state?: ExtensionSlotState;
24
- }
25
- /**
26
- * Sets the current left nav context. Must be paired with {@link unsetLeftNav}.
27
- *
28
- * @deprecated Il n'existe plus de barre latérale globale : la navigation de niveau 2 est portée par la TopBar (slot `topbar-level2-nav`, type `NavEntryMeta`). Une app qui a besoin d'une navigation interne affiche sa propre barre latérale.
29
- */
30
- export declare function setLeftNav({ name, basePath, mode, componentContext, state }: SetLeftNavParams): void;
31
- /**
32
- * Unsets the left nav context if the current context is for the supplied name.
33
- *
34
- * @deprecated Il n'existe plus de barre latérale globale : la navigation de niveau 2 est portée par la TopBar (slot `topbar-level2-nav`, type `NavEntryMeta`). Une app qui a besoin d'une navigation interne affiche sa propre barre latérale.
35
- */
36
- export declare function unsetLeftNav(name: string): void;
37
- export {};
38
- //# sourceMappingURL=left-nav.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"left-nav.d.ts","sourceRoot":"","sources":["../src/left-nav.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,KAAK,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AACrD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED,gBAAgB;AAChB,eAAO,MAAM,YAAY,0CAIvB,CAAC;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAAE,gBAAgB,QAE7F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,QAIxC"}
package/dist/left-nav.js DELETED
@@ -1,28 +0,0 @@
1
- import { createGlobalStore } from "@egen-civitas/esm-state";
2
- /** @internal */ export const leftNavStore = createGlobalStore('left-nav', {
3
- slotName: null,
4
- basePath: window.spaBase,
5
- mode: 'normal'
6
- });
7
- /**
8
- * Sets the current left nav context. Must be paired with {@link unsetLeftNav}.
9
- *
10
- * @deprecated Il n'existe plus de barre latérale globale : la navigation de niveau 2 est portée par la TopBar (slot `topbar-level2-nav`, type `NavEntryMeta`). Une app qui a besoin d'une navigation interne affiche sa propre barre latérale.
11
- */ export function setLeftNav({ name, basePath, mode, componentContext, state }) {
12
- leftNavStore.setState({
13
- slotName: name,
14
- basePath,
15
- mode: mode ?? 'normal',
16
- componentContext,
17
- state
18
- });
19
- }
20
- /**
21
- * Unsets the left nav context if the current context is for the supplied name.
22
- *
23
- * @deprecated Il n'existe plus de barre latérale globale : la navigation de niveau 2 est portée par la TopBar (slot `topbar-level2-nav`, type `NavEntryMeta`). Une app qui a besoin d'une navigation interne affiche sa propre barre latérale.
24
- */ export function unsetLeftNav(name) {
25
- if (leftNavStore.getState().slotName === name) {
26
- leftNavStore.setState(leftNavStore.getInitialState(), true);
27
- }
28
- }