@micheeeeel/yinyangapp 2.2.1 → 2.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 +3 -0
- package/dist/bundle.js +1 -1
- package/dist/types/animations/AnimationsMngr.d.ts +10 -0
- package/dist/types/api.d.ts +7 -0
- package/dist/types/components/controller/YinYangController.d.ts +167 -5
- package/dist/types/components/controller/action-stack/ActionStackController.d.ts +15 -0
- package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +40 -0
- package/dist/types/components/controller/children/ChildInteractionController.d.ts +9 -0
- package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +59 -8
- package/dist/types/components/controller/force-field/ForceFieldLifecycleController.d.ts +17 -0
- package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +25 -0
- package/dist/types/components/controller/force-field/types.d.ts +16 -0
- package/dist/types/components/controller/odd/OddHighlightEffects.d.ts +78 -0
- package/dist/types/components/controller/odd/OddViewManager.d.ts +92 -1
- package/dist/types/components/controller/odd/childHighlightStyles.d.ts +79 -0
- package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +9 -0
- package/dist/types/components/controller/state/YinYangControllerState.d.ts +23 -0
- package/dist/types/components/view/SpikeDrawer.d.ts +28 -0
- package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
- package/dist/types/config/animationConfig.d.ts +7 -0
- package/dist/types/config/propagationCometConfig.d.ts +41 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { IYinYangView } from "../../../interfaces/IYinYangView";
|
|
|
3
3
|
import { YinYangInternalModel } from "../../../interfaces/IYinYangInternalModel";
|
|
4
4
|
import { ForceFieldDetailsPanel } from "../force-field/ForceFieldDetailsPanel";
|
|
5
5
|
import { ActionStackController } from "../action-stack/ActionStackController";
|
|
6
|
+
import { OddHighlightIntensity, ChildHighlightState } from "./childHighlightStyles";
|
|
6
7
|
import type { CumulativeBlock } from "../YinYangController";
|
|
7
8
|
type ChildOddMeta = {
|
|
8
9
|
oddId: string;
|
|
@@ -27,18 +28,108 @@ type OddViewManagerDeps = {
|
|
|
27
28
|
id: string;
|
|
28
29
|
}) => CumulativeBlock[];
|
|
29
30
|
onNavigateToAction: (actionId: string) => void;
|
|
31
|
+
/** Centre orbital courant d'un satellite dans le repère du globalGroup de
|
|
32
|
+
* la facette (identique à celui que consomme WeightPreviewRingRenderer). */
|
|
33
|
+
getChildRenderedCenter: (childController: IYinYangController) => {
|
|
34
|
+
x: number;
|
|
35
|
+
y: number;
|
|
36
|
+
} | null;
|
|
37
|
+
getChildRadius: (childController: IYinYangController) => number;
|
|
38
|
+
/** Satellites atteints par la propagation de l'action en cours — exemptés
|
|
39
|
+
* de l'extinction appliquée aux non-membres. */
|
|
40
|
+
getPropagationTargetKeys: () => Set<string>;
|
|
30
41
|
};
|
|
31
42
|
export declare class OddViewManager {
|
|
32
43
|
private deps;
|
|
44
|
+
private readonly highlightEffects;
|
|
45
|
+
/** ODD mis en valeur (clic ou survol d'un arc / d'un chip de légende). */
|
|
46
|
+
private oddHighlight;
|
|
47
|
+
/** Satellite sélectionné (menu d'action ouvert) — il porte la même mise en
|
|
48
|
+
* valeur que celle d'un ODD, mais resserrée sur lui seul. */
|
|
49
|
+
private selectedChildKey;
|
|
50
|
+
/** Aperçu transitoire au survol d'un item de la pile — prioritaire tant
|
|
51
|
+
* qu'il dure, et sans effets de sélection. */
|
|
52
|
+
private stackPreviewKeys;
|
|
53
|
+
/** Laquelle des deux sélections délibérées — un ODD, ou un satellite — est
|
|
54
|
+
* la plus récente. Elles peuvent coexister (le menu d'un satellite reste
|
|
55
|
+
* ouvert quand on clique un chip d'ODD) ; c'est la dernière voulue par
|
|
56
|
+
* l'utilisateur qui porte la mise en valeur. */
|
|
57
|
+
private lastDeliberate;
|
|
58
|
+
/** Résultat des trois couches ci-dessus, relu par
|
|
59
|
+
* ChildInteractionController pour que son style "satellite actif"
|
|
60
|
+
* n'écrase pas la mise en valeur. */
|
|
61
|
+
private currentHighlight;
|
|
62
|
+
getCurrentHighlight(): ChildHighlightState;
|
|
33
63
|
constructor(deps: OddViewManagerDeps);
|
|
34
|
-
highlightOddInChildren(oddId: string | null): void;
|
|
64
|
+
highlightOddInChildren(oddId: string | null, intensity?: OddHighlightIntensity): void;
|
|
65
|
+
/**
|
|
66
|
+
* Sélectionne (ou désélectionne) le satellite qui porte la mise en valeur.
|
|
67
|
+
* Elle prime sur celle d'un ODD : sélectionner un satellite resserre le
|
|
68
|
+
* focus sur lui seul, et le relâcher rend la main à l'ODD éventuellement
|
|
69
|
+
* sélectionné.
|
|
70
|
+
*/
|
|
71
|
+
setSelectedChildHighlight(childKey: string | null): void;
|
|
72
|
+
/**
|
|
73
|
+
* Recalcule la mise en valeur effective à partir des trois couches — aperçu
|
|
74
|
+
* de pile, satellite sélectionné, ODD — puis la pose sur les satellites et
|
|
75
|
+
* synchronise les effets réservés à la sélection.
|
|
76
|
+
*/
|
|
77
|
+
private applyHighlight;
|
|
78
|
+
/**
|
|
79
|
+
* Couche gagnante. L'aperçu de pile et le survol d'un ODD priment toujours
|
|
80
|
+
* — ce sont des états transitoires, qui doivent rester lisibles même quand
|
|
81
|
+
* quelque chose est sélectionné. Entre les deux sélections durables, ODD et
|
|
82
|
+
* satellite, c'est la plus récente qui l'emporte.
|
|
83
|
+
*/
|
|
84
|
+
private resolveHighlight;
|
|
85
|
+
private buildSelectedChildLayer;
|
|
86
|
+
private buildOddLayer;
|
|
87
|
+
/**
|
|
88
|
+
* Un ODD *sélectionné* (arc actif, ou ODD affiché en vue ODD) passe en
|
|
89
|
+
* "full" ; tout le reste — au premier chef le survol d'un arc voisin —
|
|
90
|
+
* reste en "soft". Corollaire utile : quand la souris quitte un arc
|
|
91
|
+
* survolé, YinYangController retombe sur l'ODD actif, qui retrouve donc
|
|
92
|
+
* automatiquement son intensité pleine.
|
|
93
|
+
*/
|
|
94
|
+
private resolveIntensity;
|
|
95
|
+
/** Allume (ou éteint) tout ce qui n'appartient qu'à la sélection : anneaux
|
|
96
|
+
* de visée + pings + onde de scan, et spikes énergisés avec leurs
|
|
97
|
+
* comètes. */
|
|
98
|
+
private syncFullHighlightEffects;
|
|
99
|
+
/** Relu à chaque frame par OddHighlightEffects : les satellites orbitent
|
|
100
|
+
* sous les anneaux, et peuvent disparaître (satellites masqués, facette
|
|
101
|
+
* changée) sans que la mise en valeur soit repassée. */
|
|
102
|
+
private buildHighlightTargets;
|
|
35
103
|
highlightOddByStackItemId(stackItemId: string | null): void;
|
|
36
104
|
cancelOddHighlight(): void;
|
|
37
105
|
showOddInfo(oddId: string): void;
|
|
38
106
|
showComposanteInfo(): void;
|
|
39
107
|
applyOddHighlight(oddId: string): void;
|
|
40
108
|
applyEnterOddView(oddId: string): void;
|
|
109
|
+
/**
|
|
110
|
+
* Sélectionner un satellite ne sélectionne PAS son ODD : la mise en valeur
|
|
111
|
+
* d'un ODD est réservée à un clic sur l'ODD lui-même (arc du diagramme ou
|
|
112
|
+
* chip de légende). Seule subsiste ici la navigation propre à la vue ODD,
|
|
113
|
+
* qui n'affiche qu'un ODD à la fois et doit donc basculer sur celui du
|
|
114
|
+
* satellite cliqué.
|
|
115
|
+
*/
|
|
41
116
|
applyOddStateForCutting(oddId: string): void;
|
|
117
|
+
/** Repose sur un satellite le filtre que son état courant impose — utilisé
|
|
118
|
+
* après un aperçu qui l'avait écrasé (survol depuis l'arbre Recherche),
|
|
119
|
+
* pour ne pas le rendre "sans filtre" alors qu'un ODD est mis en valeur. */
|
|
120
|
+
refreshChildFilter(childController: IYinYangController): void;
|
|
121
|
+
/** Recalcule la mise en valeur sans changer de cible — appelé quand le
|
|
122
|
+
* champ de force change, puisque les satellites qu'il touche échappent à
|
|
123
|
+
* l'extinction. */
|
|
124
|
+
refreshHighlight(): void;
|
|
42
125
|
private applyChildOddHighlight;
|
|
126
|
+
/**
|
|
127
|
+
* Halo coloré d'un satellite membre : deux cercles (lueur + trait net)
|
|
128
|
+
* dans son yinYangGroup, au même endroit que l'anneau de sélection STACK
|
|
129
|
+
* (ChildScoresDeltaRenderer) — ils suivent donc l'orbite et la respiration
|
|
130
|
+
* du satellite sans aucun travail par frame, là où un drop-shadow sur le
|
|
131
|
+
* groupe était recalculé à chaque déplacement.
|
|
132
|
+
*/
|
|
133
|
+
private updateChildHaloRing;
|
|
43
134
|
}
|
|
44
135
|
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source unique du filtre CSS posé sur le groupe d'un satellite.
|
|
3
|
+
*
|
|
4
|
+
* Trois acteurs y touchaient chacun de leur côté — la mise en valeur d'un ODD
|
|
5
|
+
* (OddViewManager), le style "satellite actif" et le survol
|
|
6
|
+
* (ChildInteractionController) — et le dernier à passer gagnait : la
|
|
7
|
+
* sélection d'un ODD était effacée dès qu'un menu d'action se rafraîchissait.
|
|
8
|
+
* Tout le monde passe désormais par `resolveChildFilter`.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Deux niveaux de mise en valeur d'un ODD sur ses satellites :
|
|
12
|
+
* - "soft" (survol d'un arc) : uniquement le halo coloré des membres et
|
|
13
|
+
* l'extinction des autres. Réversible, sans animation démarrée, pour que
|
|
14
|
+
* balayer le cercle central ne fasse pas clignoter toute la constellation.
|
|
15
|
+
* - "full" (sélection) : ajoute les anneaux de visée et les pings
|
|
16
|
+
* (OddHighlightEffects), les spikes énergisés avec leurs comètes
|
|
17
|
+
* (SpikeDrawer.setOddSpikeHighlight) et l'onde de scan initiale.
|
|
18
|
+
*/
|
|
19
|
+
export type OddHighlightIntensity = "soft" | "full";
|
|
20
|
+
/**
|
|
21
|
+
* Mise en valeur courante sur les satellites d'une facette. Elle porte
|
|
22
|
+
* l'ensemble des satellites concernés plutôt qu'un ODD, parce que la même
|
|
23
|
+
* mécanique sert deux cibles : tous les satellites d'un ODD (clic sur son
|
|
24
|
+
* arc ou son chip de légende) ou le seul satellite sélectionné.
|
|
25
|
+
*/
|
|
26
|
+
export type ChildHighlightState = {
|
|
27
|
+
/** Identité de la cible — sert à ne tirer l'onde de scan qu'une fois par
|
|
28
|
+
* mise en valeur, et non à chaque re-rendu. */
|
|
29
|
+
key: string;
|
|
30
|
+
color: string;
|
|
31
|
+
intensity: OddHighlightIntensity;
|
|
32
|
+
/** Clés (`controller.getKey()`) des satellites mis en valeur. */
|
|
33
|
+
memberKeys: Set<string>;
|
|
34
|
+
} | null;
|
|
35
|
+
/** Anneau de halo posé sur le bord du satellite membre, dans la couleur de
|
|
36
|
+
* l'ODD — la même que celle de son arc dans le cercle central (voir
|
|
37
|
+
* YinYangDrawer.refreshHoverArcStyles) — pour que le lien arc ↔ satellites
|
|
38
|
+
* se lise sans avoir à le chercher. Deux traits : une lueur large et
|
|
39
|
+
* translucide, un trait net par-dessus ; largeurs en fraction du rayon. */
|
|
40
|
+
export declare const HALO_RING: Record<OddHighlightIntensity, {
|
|
41
|
+
coreWidth: number;
|
|
42
|
+
glowWidth: number;
|
|
43
|
+
coreOpacity: number;
|
|
44
|
+
glowOpacity: number;
|
|
45
|
+
}>;
|
|
46
|
+
/** Satellite dont le menu d'action est ouvert : blanc pur et plus large, pour
|
|
47
|
+
* ne pas se confondre avec un membre de l'ODD mis en valeur. */
|
|
48
|
+
export declare const ACTIVE_CHILD_FILTER = "drop-shadow(0 0 12px rgba(255, 255, 255, 0.9)) brightness(1.1)";
|
|
49
|
+
/** Survol direct d'un satellite — aperçu par-dessus tout le reste. */
|
|
50
|
+
export declare const HOVERED_CHILD_FILTER = "brightness(1.3) drop-shadow(0 0 7px rgba(255,255,255,0.4))";
|
|
51
|
+
/** Aucun ODD mis en valeur et satellite ni actif ni survolé. */
|
|
52
|
+
export declare const IDLE_CHILD_FILTER = "brightness(0.85)";
|
|
53
|
+
/** Sans transition, l'extinction des non-membres se lit comme un
|
|
54
|
+
* clignotement quand la souris balaye les arcs du cercle central. */
|
|
55
|
+
export declare const CHILD_FILTER_TRANSITION = "filter 0.22s ease-out";
|
|
56
|
+
/**
|
|
57
|
+
* Groupe sur lequel poser le filtre d'un satellite : son `globalGroup`, et
|
|
58
|
+
* surtout pas son `yinYangGroup`. Les disques yin/yang — c'est-à-dire le
|
|
59
|
+
* corps même du satellite — sont créés dans le globalGroup, en frères du
|
|
60
|
+
* yinYangGroup (voir ViewInitializer.createYinOrYangGroups) : un filtre posé
|
|
61
|
+
* sur le yinYangGroup n'atteignait presque rien, ce qui rendait toute mise
|
|
62
|
+
* en valeur invisible quelle que soit son intensité.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getChildFilterTarget(childController: {
|
|
65
|
+
view: {
|
|
66
|
+
viewInitializer: {
|
|
67
|
+
globalGroup: {
|
|
68
|
+
node: () => unknown;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
}): SVGGElement | null;
|
|
73
|
+
export declare function resolveChildFilter(params: {
|
|
74
|
+
isMember: boolean;
|
|
75
|
+
isActiveChild: boolean;
|
|
76
|
+
/** Satellite atteint par la propagation de l'action en cours. */
|
|
77
|
+
isPropagationTarget: boolean;
|
|
78
|
+
highlight: ChildHighlightState;
|
|
79
|
+
}): string;
|
|
@@ -58,6 +58,12 @@ type SearchPanelSynchronizerDeps = {
|
|
|
58
58
|
onDiagramNavChange?: (event: DiagramCuttingNavEvent) => void;
|
|
59
59
|
applyEnterOddView: (oddId: string) => void;
|
|
60
60
|
applyOddHighlight: (oddId: string) => void;
|
|
61
|
+
/** Aperçu de survol d'un ODD, `null` retombant sur l'ODD actif — même
|
|
62
|
+
* point d'entrée que le survol d'un arc du diagramme. */
|
|
63
|
+
previewOddHighlight: (oddId: string | null) => void;
|
|
64
|
+
/** Repose sur un satellite le filtre imposé par l'état courant, après un
|
|
65
|
+
* aperçu de survol qui l'avait écrasé. */
|
|
66
|
+
refreshChildFilter: (childController: IYinYangController) => void;
|
|
61
67
|
focusChildByOddCutting: (oddId: string, cuttingIndex: number, forceOpen?: boolean) => void;
|
|
62
68
|
focusChildByOddCuttingAndAction: (oddId: string, cuttingIndex: number, actionId: string) => void;
|
|
63
69
|
validateActionSelection: (childController: IYinYangController, actionId: string, label: string, insertAtVisibleIndex?: number | null, entryOrigin?: {
|
|
@@ -87,6 +93,9 @@ type SearchPanelSynchronizerDeps = {
|
|
|
87
93
|
export declare class SearchPanelSynchronizer {
|
|
88
94
|
private deps;
|
|
89
95
|
private searchHoverChildNode;
|
|
96
|
+
/** Satellite dont l'aperçu de survol est en cours — mémorisé en plus de son
|
|
97
|
+
* nœud pour pouvoir lui rendre son filtre d'état à la sortie. */
|
|
98
|
+
private searchHoverChild;
|
|
90
99
|
constructor(deps: SearchPanelSynchronizerDeps);
|
|
91
100
|
searchHandleComposanteClick(componentIndex: number): void;
|
|
92
101
|
searchNavigateToComponent(componentIndex: number): void;
|
|
@@ -100,6 +100,13 @@ export declare class YinYangControllerState {
|
|
|
100
100
|
orbitData: ChildrenOrbitEntry[] | null;
|
|
101
101
|
revealStartedAt: number | undefined;
|
|
102
102
|
selectedLinkIndex: number | null;
|
|
103
|
+
/** Item de pile en focus — persistant, posé par le clic sur l'en-tête
|
|
104
|
+
* d'un bloc du panneau de description. Survit à la navigation entre
|
|
105
|
+
* satellites et facettes ; effacé quand l'item quitte la pile active. */
|
|
106
|
+
focusedStackItemId: string | null;
|
|
107
|
+
/** Aperçu temporaire (survol d'un bloc du panneau ou d'un item de la
|
|
108
|
+
* pile) — prime sur le focus tant qu'il dure. */
|
|
109
|
+
hoveredStackItemId: string | null;
|
|
103
110
|
};
|
|
104
111
|
eventField: {
|
|
105
112
|
targets: EventFieldTarget[];
|
|
@@ -122,10 +129,21 @@ export declare class YinYangControllerState {
|
|
|
122
129
|
resetOrbitAngle(): void;
|
|
123
130
|
clearMenuActiveSelection(): void;
|
|
124
131
|
setMenuActiveChild(childKey: string | null): void;
|
|
132
|
+
/** Notifié à chaque changement du satellite sélectionné (menu d'action
|
|
133
|
+
* ouvert), quel que soit le chemin — le nombre de points d'entrée qui
|
|
134
|
+
* posent ou effacent cette sélection rend l'observation plus sûre que
|
|
135
|
+
* d'appeler la mise à jour visuelle sur chacun d'eux. */
|
|
136
|
+
private _onMenuActiveChildChange;
|
|
137
|
+
setOnMenuActiveChildChange(cb: (childKey: string | null) => void): void;
|
|
125
138
|
setActionSourceChildKey(childKey: string | null): void;
|
|
126
139
|
setMenuActiveAction(actionId: string | null): void;
|
|
127
140
|
setHasActiveChildAction(isActive: boolean): void;
|
|
128
141
|
setForceFieldSourceChildIndex(index: number): void;
|
|
142
|
+
setFocusedStackItemId(id: string | null): void;
|
|
143
|
+
setHoveredStackItemId(id: string | null): void;
|
|
144
|
+
/** Item de pile dont le satellite source porte l'emphase : l'aperçu par
|
|
145
|
+
* survol l'emporte, sinon le focus persistant. */
|
|
146
|
+
getEmphasisStackItemId(): string | null;
|
|
129
147
|
setForceFieldSourceChildIndices(indices: number[]): void;
|
|
130
148
|
setIncomingForceFieldLinks(links: ForceFieldLink[], allDetails: ForceFieldLinkDetail[]): void;
|
|
131
149
|
setForceFieldRandomCount(count: number): void;
|
|
@@ -163,6 +181,11 @@ export declare class YinYangControllerState {
|
|
|
163
181
|
setForceFieldSelectedLinkIndex(index: number | null): void;
|
|
164
182
|
setForceFieldRevealStartedAt(timestamp: number | undefined): void;
|
|
165
183
|
setForceFieldLinksAndDetails(links: ForceFieldLink[], allLinkDetails: ForceFieldLinkDetail[]): void;
|
|
184
|
+
/** Notifié à chaque recomposition des liens du champ de force — les
|
|
185
|
+
* satellites qu'ils touchent échappent à l'extinction appliquée par une
|
|
186
|
+
* mise en valeur (voir resolveChildFilter). */
|
|
187
|
+
private _onForceFieldLinksChange;
|
|
188
|
+
setOnForceFieldLinksChange(cb: () => void): void;
|
|
166
189
|
setEventFieldTargets(targets: EventFieldTarget[]): void;
|
|
167
190
|
setEventFieldFrameId(frameId: number | undefined): void;
|
|
168
191
|
setEventFieldLastTimestamp(timestamp: number | undefined): void;
|
|
@@ -8,6 +8,13 @@ export declare class SpikeDrawer {
|
|
|
8
8
|
spikesEnabled: boolean;
|
|
9
9
|
private spikeGhostEntries;
|
|
10
10
|
private spikeGhostFrameId;
|
|
11
|
+
/** ODD actuellement sélectionné dans le cercle central (clic sur un arc) :
|
|
12
|
+
* ses spikes restent énergisés en continu et une comète les remonte.
|
|
13
|
+
* Mémorisé parce qu'unhighlightSpikes() est appelé au mouseleave d'un
|
|
14
|
+
* satellite et ne doit pas éteindre au passage la sélection en cours. */
|
|
15
|
+
private oddSpikeHighlight;
|
|
16
|
+
private oddCometEntries;
|
|
17
|
+
private oddCometFrameId;
|
|
11
18
|
constructor(ViewInitializer: ViewInitializer);
|
|
12
19
|
/**
|
|
13
20
|
* Initializes the necessary data for drawing spikes.
|
|
@@ -57,4 +64,25 @@ export declare class SpikeDrawer {
|
|
|
57
64
|
* Restores all spikes to their default appearance.
|
|
58
65
|
*/
|
|
59
66
|
unhighlightSpikes(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Énergise en continu les spikes de l'ODD sélectionné — la ligne de force
|
|
69
|
+
* qui relie son arc du cercle central à chacun de ses satellites — et
|
|
70
|
+
* éteint les autres, puis lance les comètes qui les remontent. `oddId` à
|
|
71
|
+
* null rend leur apparence par défaut à tous les spikes.
|
|
72
|
+
*
|
|
73
|
+
* C'est l'effet qui *montre* le rattachement satellite ↔ ODD, là où le
|
|
74
|
+
* halo posé sur les satellites (voir OddViewManager) ne fait que le
|
|
75
|
+
* suggérer. Réservé à l'intensité "full" (clic).
|
|
76
|
+
*/
|
|
77
|
+
setSpikeHighlight(target: {
|
|
78
|
+
oddId: string;
|
|
79
|
+
cuttingIndex?: number;
|
|
80
|
+
} | null, color: string): void;
|
|
81
|
+
/** Vrai si ce spike fait partie de la mise en valeur courante. */
|
|
82
|
+
private isHighlightedSpike;
|
|
83
|
+
private forEachSpikeLine;
|
|
84
|
+
private applyOddSpikeHighlight;
|
|
85
|
+
private refreshOddSpikeComets;
|
|
86
|
+
private ensureOddCometLoop;
|
|
87
|
+
private clearOddSpikeComets;
|
|
60
88
|
}
|