ep-lib-ts 1.0.46 → 1.0.48

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 (156) hide show
  1. package/dist/BgAudio-kLycvFEF.js +4 -0
  2. package/dist/Details-Op3Zkhcg.js +4 -0
  3. package/dist/DisplayBox-DGsKoxmr.js +4 -0
  4. package/dist/{Ep360Image-CQJBPImD.js → Ep360Image-DHK_IWTi.js} +1 -1
  5. package/dist/{Ep360Video-CL_7mOiQ.js → Ep360Video-C4PekHTc.js} +1 -1
  6. package/dist/EpAlert-aWrJokXa.js +4 -0
  7. package/dist/EpAudio-DGFoC0Go.js +4 -0
  8. package/dist/EpAvatar-1yU-OXsu.js +4 -0
  9. package/dist/EpBadge-BlIhFCIg.js +4 -0
  10. package/dist/EpBarChart-KgYdXvMq.js +4 -0
  11. package/dist/EpBtn-S1mCeeV7.js +4 -0
  12. package/dist/EpCard-COy2GODb.js +4 -0
  13. package/dist/EpCardLink-SBppyTrI.js +4 -0
  14. package/dist/EpChip-CNRaxrjP.js +4 -0
  15. package/dist/EpCodeblock-NyXHH5gD.js +4 -0
  16. package/dist/EpConclusion-CUWiK_nt.js +4 -0
  17. package/dist/EpContentSlider-mpqkd2T2.js +4 -0
  18. package/dist/{EpDarkmode-DyUrMSO5.js → EpDarkmode-C5NMN4h2.js} +1 -1
  19. package/dist/EpDescription-Dewh9Bmr.js +4 -0
  20. package/dist/EpDivider-C_cgaXNK.js +4 -0
  21. package/dist/EpDocument-CmN-KUVt.js +4 -0
  22. package/dist/{EpDraggable-CTWqRQzE.js → EpDraggable-BwpIpRyf.js} +74 -74
  23. package/dist/EpEdu-BRXEfH5H.js +4 -0
  24. package/dist/EpFlex-UUXOmWtZ.js +4 -0
  25. package/dist/EpFunnelChart-DgkcR1ON.js +4 -0
  26. package/dist/EpHeader-DeiRUZRl.js +4 -0
  27. package/dist/EpHover-BKK7j48J.js +4 -0
  28. package/dist/EpHoverCard-6ZKNpNBq.js +4 -0
  29. package/dist/EpIcon-C3jjducH.js +4 -0
  30. package/dist/EpIframe-CoaO5gb_.js +4 -0
  31. package/dist/EpImg-iypQu6WK.js +4 -0
  32. package/dist/EpImgCarousel-vagns6kd.js +4 -0
  33. package/dist/{EpInput-CGnN-piP.js → EpInput-uDeg10dD.js} +30 -30
  34. package/dist/EpInstructions-C2JYulUa.js +4 -0
  35. package/dist/EpIntroduction-BJXDxfYV.js +4 -0
  36. package/dist/EpLineChart-BVlswUIa.js +4 -0
  37. package/dist/EpLink-DPR3gH7f.js +4 -0
  38. package/dist/EpLinkVersion-DqQvfQQT.js +4 -0
  39. package/dist/{EpList-C8uaLum6.js → EpList-BI7oPTHl.js} +1 -1
  40. package/dist/EpModal-DN-QQzrQ.js +4 -0
  41. package/dist/{EpNothing-DxfGfasN.js → EpNothing-z596jG9D.js} +1 -1
  42. package/dist/EpObjective-sNcUzMGj.js +4 -0
  43. package/dist/EpPieChart-CCgGmemH.js +4 -0
  44. package/dist/EpQuestion-DJ-1vSS6.js +4 -0
  45. package/dist/EpQuote-BWRF6A-L.js +4 -0
  46. package/dist/EpRadio-BLbK_ijo.js +4 -0
  47. package/dist/EpRadioSummative-BtiAeyHR.js +4 -0
  48. package/dist/EpReading-C78Icl4m.js +4 -0
  49. package/dist/EpResource-C_JQvg2g.js +4 -0
  50. package/dist/EpScope-D1e7l9RQ.js +4 -0
  51. package/dist/EpSection-C9VobPvp.js +4 -0
  52. package/dist/EpSectionCols-D9DqSfNG.js +4 -0
  53. package/dist/EpSkeleton-Cc3nfQlv.js +4 -0
  54. package/dist/EpSoftware-Bga9b4WM.js +4 -0
  55. package/dist/EpSpecificObjective-C9MHA7ez.js +4 -0
  56. package/dist/EpSpinner-BOpURQEs.js +4 -0
  57. package/dist/EpStackedList-BdIF2Obj.js +4 -0
  58. package/dist/EpSummativeTable-BTLrKIHA.js +4 -0
  59. package/dist/EpSvg-CJfC1DMY.js +4 -0
  60. package/dist/EpSvgShow-SnjMv4b2.js +4 -0
  61. package/dist/EpTable--hx3As1M.js +4 -0
  62. package/dist/EpTerm-l4uolPHU.js +4 -0
  63. package/dist/EpText-Dvi-oAJe.js +4 -0
  64. package/dist/EpTimeLine-BeRMD8rW.js +4 -0
  65. package/dist/EpVideo-D4DR93ep.js +4 -0
  66. package/dist/EpVideoPanopto-CVjjy9Nn.js +4 -0
  67. package/dist/EpWordDef-DRBqhyxR.js +4 -0
  68. package/dist/TextMedia-LKMaVja3.js +4 -0
  69. package/dist/components/educationals/EpBranchingScenario.vue.d.ts +43 -5
  70. package/dist/components/educationals/EpDocument.vue.d.ts +44 -0
  71. package/dist/components/interactions/EpSvgShow.vue.d.ts +0 -1
  72. package/dist/components/medias/EpHierarchy.vue.d.ts +51 -0
  73. package/dist/components/medias/EpSoftware.vue.d.ts +0 -1
  74. package/dist/components/tools/Details.vue.d.ts +36 -0
  75. package/dist/components/tools/TextMedia.vue.d.ts +25 -0
  76. package/dist/ep-lib-ts.js +44 -40
  77. package/dist/ep-lib-ts.umd.cjs +212 -212
  78. package/dist/{index-IdtPmXeP.js → index-CO05CQPt.js} +461 -514
  79. package/dist/{index-D5QYJLNE.js → index-DH1gIdAA.js} +1 -1
  80. package/dist/{index-FmXc2ivj.js → index-DeiLPw0s.js} +10876 -7941
  81. package/dist/index.d.ts +5 -1
  82. package/dist/{prism-D-x8E1YK.js → prism-BvbRGWPO.js} +1 -1
  83. package/dist/style.css +1 -1
  84. package/dist/{three.module-CWLs6nMo.js → three.module-B-oqC8Xk.js} +1 -1
  85. package/dist/types/Component.d.ts +7 -0
  86. package/dist/types/Hierarchy.d.ts +14 -0
  87. package/package.json +11 -1
  88. package/src/components/basics/EpBtn.vue +1 -1
  89. package/src/components/educationals/EpBranchingScenario.vue +202 -124
  90. package/src/components/educationals/EpDocument.vue +92 -0
  91. package/src/components/interactions/EpContentSlider.vue +1 -1
  92. package/src/components/interactions/EpDraggable.vue +4 -4
  93. package/src/components/interactions/EpSvgShow.vue +66 -66
  94. package/src/components/medias/EpHierarchy.vue +345 -0
  95. package/src/components/medias/EpSoftware.vue +1 -2
  96. package/src/components/tools/Details.vue +46 -0
  97. package/src/components/tools/TextMedia.vue +34 -0
  98. package/dist/BgAudio-ryf2FIxF.js +0 -4
  99. package/dist/DisplayBox-ky90shjr.js +0 -4
  100. package/dist/EpAlert-BUiXiWRL.js +0 -4
  101. package/dist/EpAudio-CkZrkt3Z.js +0 -4
  102. package/dist/EpAvatar-2ZL5g8-2.js +0 -4
  103. package/dist/EpBadge-vOdZrc0e.js +0 -4
  104. package/dist/EpBarChart-CUUaOMsS.js +0 -4
  105. package/dist/EpBranchingScenario-DT2VQz7o.js +0 -160
  106. package/dist/EpBtn-DD0ykcYq.js +0 -4
  107. package/dist/EpCard-Qgkskboo.js +0 -4
  108. package/dist/EpCardLink-BfTUOLcA.js +0 -4
  109. package/dist/EpChip-P7j6l0PH.js +0 -4
  110. package/dist/EpCodeblock-DpzMd_h0.js +0 -4
  111. package/dist/EpConclusion-BRBOGFVk.js +0 -4
  112. package/dist/EpContentSlider-KFhPqR1h.js +0 -4
  113. package/dist/EpDescription-CcdsFWCf.js +0 -4
  114. package/dist/EpDivider-C30UAjvv.js +0 -4
  115. package/dist/EpEdu-CApC3SiS.js +0 -4
  116. package/dist/EpFlex-Dgc5dinh.js +0 -4
  117. package/dist/EpFunnelChart-Xm34GDMu.js +0 -4
  118. package/dist/EpHeader-DSKKm621.js +0 -4
  119. package/dist/EpHover-KHdqQJ6y.js +0 -4
  120. package/dist/EpHoverCard-Ccl2Un2s.js +0 -4
  121. package/dist/EpIcon-Eezd-EUx.js +0 -4
  122. package/dist/EpIframe-CmEsIYyW.js +0 -4
  123. package/dist/EpImg-BV_rS7v3.js +0 -4
  124. package/dist/EpImgCarousel-BHade9dP.js +0 -4
  125. package/dist/EpInstructions-A6ajkYEJ.js +0 -4
  126. package/dist/EpIntroduction-BY39wrQW.js +0 -4
  127. package/dist/EpLineChart-DQNIlO9r.js +0 -4
  128. package/dist/EpLink-BdxmUlWG.js +0 -4
  129. package/dist/EpLinkVersion-BAsA6tzp.js +0 -4
  130. package/dist/EpModal-DIEKXVnQ.js +0 -4
  131. package/dist/EpObjective-DwnP_7Zm.js +0 -4
  132. package/dist/EpPieChart-DmcML2d-.js +0 -4
  133. package/dist/EpQuestion-D7-nzMHE.js +0 -4
  134. package/dist/EpQuote-Cb5Ty6Ec.js +0 -4
  135. package/dist/EpRadio-9V6iAh4n.js +0 -4
  136. package/dist/EpRadioSummative-BL2YhCK3.js +0 -4
  137. package/dist/EpReading-DTWjzj6l.js +0 -4
  138. package/dist/EpResource-ZMfXpSqf.js +0 -4
  139. package/dist/EpScope-1aCF0beo.js +0 -4
  140. package/dist/EpSection-C-GaZN4R.js +0 -4
  141. package/dist/EpSectionCols-ap4Z5x7P.js +0 -4
  142. package/dist/EpSkeleton-DQUHmKio.js +0 -4
  143. package/dist/EpSoftware-DdF8BdqQ.js +0 -4
  144. package/dist/EpSpecificObjective-44uQGH3u.js +0 -4
  145. package/dist/EpSpinner-DHU8EZRf.js +0 -4
  146. package/dist/EpStackedList-BBGlTBx6.js +0 -4
  147. package/dist/EpSummativeTable-Cz4gcxHT.js +0 -4
  148. package/dist/EpSvg-Dk_q0cGB.js +0 -4
  149. package/dist/EpSvgShow-Cb_Y5UGq.js +0 -54
  150. package/dist/EpTable-Cg3-lRZY.js +0 -4
  151. package/dist/EpTerm-CRkB0QyE.js +0 -4
  152. package/dist/EpText-Dj93fveo.js +0 -4
  153. package/dist/EpTimeLine-Cit4tc3F.js +0 -4
  154. package/dist/EpVideo-1obD7bUC.js +0 -4
  155. package/dist/EpVideoPanopto-DzkzWyOF.js +0 -4
  156. package/dist/EpWordDef-DIjwoqzN.js +0 -4
@@ -39,7 +39,7 @@ const updateSize = () => {
39
39
  const rect = myImage.value.getBoundingClientRect();
40
40
  actualRect.value = { width: rect.width, height: rect.height };
41
41
 
42
- console.log('Image size updated. Width:', actualRect.value.width, 'Height:', actualRect.value.height);
42
+ //console.log('Image size updated. Width:', actualRect.value.width, 'Height:', actualRect.value.height);
43
43
  };
44
44
 
45
45
 
@@ -56,7 +56,7 @@ const handleImageLoad = (event: any) => {
56
56
  originalWidth.value = event.target.naturalWidth;
57
57
  originalHeight.value = event.target.naturalHeight;
58
58
 
59
- console.log('Image loaded. Width:', originalWidth.value, 'Height:', originalHeight.value);
59
+ // console.log('Image loaded. Width:', originalWidth.value, 'Height:', originalHeight.value);
60
60
 
61
61
  updateSize();
62
62
  }
@@ -93,7 +93,7 @@ const choices = ref<Choice[]>( props.sockets.map((s) => {
93
93
 
94
94
  // Manage drag and drop
95
95
  const onAdd = (event: any, index: number) => {
96
- console.log(event.clone);
96
+ // console.log(event.clone);
97
97
 
98
98
  // Retirer l'élément de la liste des réponses disponibles
99
99
  availableAnswers.value = availableAnswers.value.filter(item => item.name !== event.clone.name);
@@ -101,7 +101,7 @@ const onAdd = (event: any, index: number) => {
101
101
  }
102
102
 
103
103
  const onRemove = (event: any, index: number) => {
104
- console.log(event.clone);
104
+ // console.log(event.clone);
105
105
 
106
106
  choices.value[index].choice = [];
107
107
  choices.value[index].allowPut = true;
@@ -2,96 +2,96 @@
2
2
  import { onMounted, ref, computed, nextTick } from 'vue';
3
3
  import { useRenderText } from '../../composables/useRenderText';
4
4
 
5
-
6
-
7
5
  interface Props {
8
- svg: string,
9
- id: string,
10
- animation?: "" | "translateX" | "scale",
11
- multiple?: boolean
6
+ svg: string,
7
+ animation?: "" | "translateX" | "scale",
8
+ multiple?: boolean
12
9
  }
13
10
 
14
-
15
11
  const props = withDefaults(defineProps<Props>(), {
16
- animation: "",
17
- multiple: false
12
+ animation: "",
13
+ multiple: false
18
14
  });
19
15
 
20
16
  const svg = ref<string>("");
21
17
 
18
+ // Refs
19
+ const svgContainer = ref<HTMLElement | null>(null);
20
+
22
21
  const animationType = computed(() => {
23
- switch (props.animation) {
24
- case "translateX":
25
- return "animate-slide";
26
- case "scale":
27
- return "animate-zoom";
28
- default:
29
- return "animate-fade";
30
- }
22
+ switch (props.animation) {
23
+ case "translateX":
24
+ return "animate-slide";
25
+ case "scale":
26
+ return "animate-zoom";
27
+ default:
28
+ return "animate-fade";
29
+ }
31
30
  });
32
31
 
33
-
34
-
35
-
36
-
37
- onMounted(async() => {
38
- svg.value = useRenderText(props.svg);
39
-
40
- await nextTick();
41
-
42
- // manage the scenes
43
- const scenes = document.getElementById(props.id)?.getElementsByClassName('scene');
44
-
45
- if(scenes) {
46
- Array.from(scenes).forEach((s) => {
47
- if(!s.classList.contains('hidden')) {
48
- s.classList.add('hidden');
49
- }
50
- });
32
+ const showScene = (scene: string) => {
33
+ if (!svgContainer.value) return;
34
+ const currentScene = svgContainer.value.querySelector(`[data-scene="${scene}"]`)
35
+ if(!currentScene) return;
36
+ if(!props.multiple){
37
+ hideScenes()
38
+ }
39
+ currentScene.classList.remove('hidden', animationType.value)
40
+ currentScene.classList.add(animationType.value)
41
+ // const scenes = svgContainer.value.getElementsByClassName('scene');
42
+ // Array.from(scenes).forEach((s) => {
43
+ // if (s.classList.contains(`scene-${scene}`)) {
44
+ // s.classList.remove('hidden', animationType.value);
45
+ // s.classList.add(animationType.value);
46
+ // } else {
47
+ // if (!props.multiple && !s.classList.contains('hidden')) {
48
+ // s.classList.add('hidden');
49
+ // s.classList.remove(animationType.value);
50
+ // }
51
+ // }
52
+ // });
53
+ };
54
+
55
+ const hideScenes = () => {
56
+ if (!svgContainer.value) return;
57
+ const scenes = svgContainer.value.querySelectorAll('[data-scene]');
58
+ Array.from(scenes).forEach((s) => {
59
+ if (!s.classList.contains('hidden')) {
60
+ s.classList.add('hidden');
61
+ s.classList.remove(animationType.value);
51
62
  }
63
+ });
64
+ }
52
65
 
53
- // manage the buttons
54
- const btns = document.getElementById(props.id)?.getElementsByClassName('btn');
66
+ onMounted(async () => {
67
+ svg.value = useRenderText(props.svg);
55
68
 
56
- if(btns) {
57
- Array.from(btns).forEach((b) => {
58
- b.addEventListener('click', (e) => {
59
- const scene = b.getAttribute("id");
60
- showScene(scene?? "");
61
- });
62
- });
63
- }
64
- });
69
+ await nextTick();
65
70
 
71
+ if (!svgContainer.value) return;
66
72
 
73
+ // Hide all scenes initially
74
+ hideScenes()
67
75
 
68
- const showScene = (scene: string) => {
69
- console.log('event', scene);
70
- if(svg.value) {
71
- const scenes = document.getElementById(props.id)?.getElementsByClassName('scene');
72
- if(scenes) {
73
- Array.from(scenes).forEach((s) => {
74
- if (s.classList.contains(`scene-${scene}`)) {
75
- s.classList.remove('hidden', animationType.value);
76
- s.classList.add(animationType.value);
77
- } else {
78
- if(!props.multiple && !s.classList.contains('hidden')) {
79
- s.classList.add('hidden');
80
- s.classList.remove(animationType.value);
81
- }
82
- }
83
- });
84
- }
85
- }
86
- }
76
+ // Bind click events to buttons
77
+ const btns = svgContainer.value.querySelectorAll('[data-btn]');
78
+ Array.from(btns).forEach((b) => {
79
+ b.classList.add('cursor-pointer')
80
+ b.addEventListener('click', () => {
81
+ const sceneName = b.getAttribute("data-btn")
82
+ showScene(sceneName ?? "");
83
+ });
84
+ });
85
+ });
87
86
 
88
87
 
89
88
 
90
89
  </script>
91
90
 
92
91
 
92
+
93
93
  <template>
94
94
  <!-- The buttons must have class "btn" and an unique id="<scene-name>"
95
95
  The scenes elements must have class "scene" and "scene-<scene-name>" -->
96
- <div :id="id" v-html="svg"></div>
96
+ <div ref="svgContainer" v-html="svg"></div>
97
97
  </template>
@@ -0,0 +1,345 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted, computed, defineAsyncComponent } from 'vue'
3
+ import { hierarchy, tree, cluster, type HierarchyPointLink, type HierarchyPointNode } from 'd3-hierarchy'
4
+ import * as d3 from 'd3-selection'
5
+ import { linkVertical, linkHorizontal } from 'd3-shape'
6
+ //import { ascending } from 'd3-array'
7
+ import * as d3Zoom from 'd3-zoom'
8
+ import type { TreeNode, ColorPath, ColorRect } from '../../types/Hierarchy'
9
+ import type { NestedComponents } from '../../types/Component'
10
+ import { useComponent } from '../../composables/useComponent'
11
+ import EpModal from '../interactions/EpModal.vue'
12
+ import EpBtn from '../basics/EpBtn.vue'
13
+ import { useRenderText } from '../../composables/useRenderText'
14
+
15
+
16
+
17
+ interface Props {
18
+ nodes: TreeNode;
19
+ maxWidth?: number;
20
+ maxHeight?: number;
21
+ labelClose?: string;
22
+ isCluster?:boolean;
23
+ colorPath?:ColorPath;
24
+ colorRect?:ColorRect;
25
+ }
26
+
27
+ const props = withDefaults(defineProps<Props>(), {
28
+ labelClose: "fermer",
29
+ maxWidth: 800,
30
+ maxHeight: 600,
31
+ isCluster:false,
32
+ colorRect:'fill-main-color-400',
33
+ colorPath:'stroke-yellow-400'
34
+ })
35
+
36
+ const treeContainer = ref<HTMLDivElement | null>(null)
37
+ const treeWrapper = ref<HTMLDivElement | null>(null)
38
+
39
+
40
+ /* control modal */
41
+ type ShowNode = {
42
+ title: string;
43
+ text?: string;
44
+ component?: NestedComponents
45
+ }
46
+
47
+ const currentNode = ref<ShowNode | null>(null)
48
+ const showModal = ref(false)
49
+
50
+ const handleNodeClick = (node: TreeNode) => {
51
+ currentNode.value = {
52
+ title: node.name,
53
+ text: node.text,
54
+ component: node.component
55
+ }
56
+ showModal.value = true
57
+ }
58
+
59
+ const closeModal = () => {
60
+ showModal.value = false
61
+ currentNode.value = null
62
+ }
63
+
64
+ const currentRenderComponent = computed(() => {
65
+ if (currentNode.value && currentNode.value.component) {
66
+ const componentToLoad = useComponent(currentNode.value.component.type);
67
+ return defineAsyncComponent(() => import(`../${componentToLoad.path}/${componentToLoad.name}.vue`));
68
+ }
69
+ return null;
70
+ });
71
+
72
+ onMounted(() => {
73
+ if (!treeContainer.value) return
74
+
75
+ if(props.isCluster){
76
+ clusterView()
77
+ }else{
78
+ treeView()
79
+ }
80
+
81
+
82
+
83
+ })
84
+
85
+
86
+ const treeView = () => {
87
+ const rectW = 130
88
+ const rectH = 40
89
+ const margin = { top: 40, right: 40, bottom: 40, left: 40 }
90
+
91
+ const root = hierarchy<TreeNode>(props.nodes)
92
+ //const totalLeafCount = root.leaves().length
93
+ const width = Math.max(props.maxWidth)
94
+ const height = props.maxHeight
95
+
96
+ const treeLayout = tree<TreeNode>()
97
+ .nodeSize([170, 100]) // [x spacing, y spacing]
98
+
99
+ const treeData = treeLayout(root)
100
+
101
+ const svg = d3.select(treeContainer.value)
102
+ .append('svg')
103
+ .attr('width', width)
104
+ .attr('height', height)
105
+
106
+ const g = svg.append('g')
107
+ .attr('transform', `translate(${margin.left}, ${margin.top})`)
108
+
109
+ const zoom = d3Zoom.zoom<SVGSVGElement, unknown>()
110
+ .scaleExtent([0.5, 2])
111
+ .on('zoom', (event) => {
112
+ g.attr('transform', event.transform)
113
+ })
114
+
115
+ svg.call(zoom)
116
+
117
+ const centerX = width / 2 - treeData.x
118
+ const centerY = 30//height / 2 - treeData.y
119
+ const identity = (d3Zoom as any).zoomIdentity
120
+ svg.call(zoom.transform, identity.translate(centerX, centerY))
121
+
122
+ // Links
123
+ const linkPath = linkVertical<HierarchyPointLink<TreeNode>, HierarchyPointNode<TreeNode>>()
124
+ .x(d => d.x)
125
+ .y(d => d.y)
126
+
127
+ g.selectAll('path.link')
128
+ .data(treeData.links())
129
+ .enter()
130
+ .append('path')
131
+ .attr('d', d => linkPath(d))
132
+ .attr('class', d => {
133
+ const link = d.target.data.active ? `${props.colorPath} stroke-2` : 'stroke-black dark:stroke-white'
134
+ return `${link} link fill-none`
135
+ })
136
+
137
+ // Nodes
138
+ const node = g.selectAll('g.node')
139
+ .data(treeData.descendants())
140
+ .enter()
141
+ .append('g')
142
+ .attr('class', 'node')
143
+ .attr('transform', d => `translate(${d.x}, ${d.y})`)
144
+ .style('cursor', d => (d.data.component || d.data.text ? 'pointer' : 'default'))
145
+ .each(function (d) {
146
+ if (d.data.component || d.data.text) {
147
+ d3.select(this).on('click', (_event) => handleNodeClick(d.data))
148
+ }
149
+ })
150
+ //.style('cursor', 'pointer')
151
+ //.on('click', (_event, d) => handleNodeClick(d.data))
152
+
153
+ node.each(function (d) {
154
+ const group = d3.select(this)
155
+
156
+ // Append text temporarily
157
+ const text = group.append('text')
158
+ .attr('class', 'text-sm font-semibold fill-black dark:fill-white')
159
+ .attr('text-anchor', 'middle')
160
+ .attr('x', 0)
161
+ .attr('y', 0)
162
+ .attr('dy', '.35em')
163
+ .text(d.data.name)
164
+
165
+ // Get bounding box to determine text size
166
+ const bbox = (text.node() as SVGTextElement).getBBox()
167
+ const paddingX = 10
168
+ const paddingY = 10
169
+
170
+ const width = bbox.width + paddingX * 2
171
+ const height = bbox.height + paddingY * 2
172
+
173
+ // Draw rect using text size
174
+ group.insert('rect', 'text')
175
+ .attr('class', props.colorRect)
176
+ .attr('x', -width / 2)
177
+ .attr('y', -height / 2)
178
+ .attr('width', width)
179
+ .attr('height', height)
180
+ .attr('rx', 4)
181
+ .attr('ry', 4)
182
+ })
183
+
184
+
185
+ node.append('text')
186
+ .attr('x', 0)
187
+ .attr('y', 0)
188
+ .attr('dy', '.35em')
189
+ .attr('class', 'text-sm font-semibold fill-white dark:fill-black')
190
+ .attr('text-anchor', 'middle')
191
+ .text(d => d.data.name)
192
+ .style('pointer-events', 'none')
193
+ }
194
+
195
+ const clusterView = () => {
196
+ const rectW = 130
197
+ const rectH = 40
198
+ const margin = { top: 40, right: 40, bottom: 40, left: 40 }
199
+
200
+ const root = hierarchy<TreeNode>(props.nodes)
201
+ //const totalLeafCount = root.leaves().length
202
+ const width = Math.max(props.maxWidth)
203
+ const height = props.maxHeight
204
+
205
+ const treeLayout = cluster<TreeNode>()
206
+ .nodeSize([130, 130]) // [x spacing, y spacing]
207
+
208
+ const treeData = treeLayout(root)
209
+
210
+ const svg = d3.select(treeContainer.value)
211
+ .append('svg')
212
+ .attr('width', width)
213
+ .attr('height', height)
214
+
215
+ const g = svg.append('g')
216
+ .attr('transform', `translate(${margin.left}, ${margin.top})`)
217
+
218
+ const zoom = d3Zoom.zoom<SVGSVGElement, unknown>()
219
+ .scaleExtent([0.1, 4])
220
+ .on('zoom', (event) => {
221
+ g.attr('transform', event.transform)
222
+ })
223
+
224
+ svg.call(zoom)
225
+
226
+ const centerX = 30
227
+ const centerY = height / 2 - treeData.x
228
+ const identity = (d3Zoom as any).zoomIdentity
229
+ svg.call(zoom.transform, identity.translate(centerX, centerY))
230
+
231
+ // Links
232
+ const linkPath = linkHorizontal<HierarchyPointLink<TreeNode>, HierarchyPointNode<TreeNode>>()
233
+ .x(d => d.y)
234
+ .y(d => d.x)
235
+
236
+ g.selectAll('path.link')
237
+ .data(treeData.links())
238
+ .enter()
239
+ .append('path')
240
+ .attr('d', d => linkPath(d))
241
+ .attr('class', d => {
242
+ const link = d.target.data.active ? `${props.colorPath} stroke-2` : 'stroke-black dark:stroke-white'
243
+ return `${link} link fill-none`
244
+ })
245
+
246
+ // Nodes
247
+ const node = g.selectAll('g.node')
248
+ .data(treeData.descendants())
249
+ .enter()
250
+ .append('g')
251
+ .attr('class', 'node')
252
+ .attr('transform', d => `translate(${d.y}, ${d.x})`)
253
+ .style('cursor', d => (d.data.component || d.data.text ? 'pointer' : 'default'))
254
+ .each(function (d) {
255
+ if (d.data.component || d.data.text) {
256
+ d3.select(this).on('click', (_event) => handleNodeClick(d.data))
257
+ }
258
+ })
259
+ //.style('cursor', 'pointer')
260
+ //.on('click', (_event, d) => handleNodeClick(d.data))
261
+
262
+ node.each(function (d) {
263
+ const group = d3.select(this)
264
+
265
+ // Append text temporarily
266
+ const text = group.append('text')
267
+ .attr('class', 'text-sm font-semibold fill-black dark:fill-white')
268
+ .attr('text-anchor', 'middle')
269
+ .attr('x', 0)
270
+ .attr('y', 0)
271
+ .attr('dy', '.35em')
272
+ .text(d.data.name)
273
+
274
+ // Get bounding box to determine text size
275
+ const bbox = (text.node() as SVGTextElement).getBBox()
276
+ const paddingX = 10
277
+ const paddingY = 10
278
+
279
+ const width = bbox.width + paddingX * 2
280
+ const height = bbox.height + paddingY * 2
281
+
282
+ // Draw rect using text size
283
+ group.insert('rect', 'text')
284
+ .attr('class', props.colorRect)
285
+ .attr('x', -width / 2)
286
+ .attr('y', -height / 2)
287
+ .attr('width', width)
288
+ .attr('height', height)
289
+ .attr('rx', 4)
290
+ .attr('ry', 4)
291
+ })
292
+
293
+
294
+ node.append('text')
295
+ .attr('x', 0)
296
+ .attr('y', 0)
297
+ .attr('dy', '.35em')
298
+ .attr('class', 'text-sm font-semibold fill-white dark:fill-black')
299
+ .attr('text-anchor', 'middle')
300
+ .text(d => d.data.name)
301
+ .style('pointer-events', 'none')
302
+ }
303
+
304
+
305
+
306
+
307
+ const maxW = computed(() => {
308
+ return `${props.maxWidth.toString()}px`
309
+ })
310
+
311
+ const maxH = computed(() => {
312
+ return `${props.maxWidth.toString()}px`
313
+ })
314
+
315
+ </script>
316
+
317
+
318
+ <template>
319
+ <div>
320
+ <div ref="treeWrapper" class="tree-wrapper mx-auto" :style="{ maxHeight: maxH, maxWidth: maxW }">
321
+ <div ref="treeContainer" class="tree-container"></div>
322
+ </div>
323
+ <EpModal v-model="showModal" :title="currentNode.title" v-if="currentNode">
324
+ <div v-if="currentNode.text" v-html="useRenderText(currentNode.text)"></div>
325
+ <template v-if="currentRenderComponent && currentNode.component">
326
+ <component :is="currentRenderComponent" v-bind="{ ...currentNode.component.data }" />
327
+ </template>
328
+ <div class="flex justify-end">
329
+ <EpBtn @click="closeModal" type="error" outlined rounded>{{ labelClose }}</EpBtn>
330
+ </div>
331
+ </EpModal>
332
+ </div>
333
+ </template>
334
+
335
+ <style scoped>
336
+ .tree-wrapper {
337
+ overflow: auto;
338
+ border: 1px solid #ddd;
339
+ }
340
+
341
+ .tree-container {
342
+ width: 100%;
343
+ overflow-x: auto;
344
+ }
345
+ </style>
@@ -17,7 +17,6 @@ interface Props {
17
17
  title: string;
18
18
  mandateLevel?:MandateLevel | null;
19
19
  intentions?: string;
20
- version_link?: null;
21
20
  hideCover?: boolean;
22
21
  version?: string;
23
22
  type?:MediaVariants;
@@ -65,7 +64,7 @@ const { title, intentions, cover, hideCover, version, labelCard, hideIcon, manda
65
64
  <template v-if="!hideCover">
66
65
  <img
67
66
  v-if="hasCover"
68
- class="object-cover h-24 w-full rounded-t-lg object-cover md:h-auto md:w-24 md:rounded-none md:rounded-l-lg"
67
+ class="h-24 w-full rounded-t-lg object-cover md:h-auto md:w-24 md:rounded-none md:rounded-l-lg"
69
68
  :src="cover"
70
69
  :alt="`image de la lecture ${title}`"
71
70
  />
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import {ref} from 'vue'
3
+ import EpModal from '../interactions/EpModal.vue';
4
+ import type { NestedComponents } from '../../types/Component';
5
+ import EpBtn from '../basics/EpBtn.vue';
6
+ import EpDivider from '../basics/EpDivider.vue';
7
+ import TextMedia from './TextMedia.vue';
8
+ const showModal = ref(false)
9
+
10
+
11
+ interface Props {
12
+ title?:string;
13
+ content:string;
14
+ labelClose?:string;
15
+ media?:NestedComponents
16
+ }
17
+
18
+ const props = withDefaults(defineProps<Props>(), {
19
+ title:"Voir détails",
20
+ labelClose:"Fermer"
21
+ })
22
+
23
+ </script>
24
+
25
+ <template>
26
+ <div class="cursor-pointer rounded bg-primary text-white py-2 px-4 flex flex-col items-center" @click="showModal = true">
27
+ <EpModal v-model="showModal" :title="content">
28
+ <TextMedia
29
+ :text="title"
30
+ :media="media"
31
+ />
32
+ <EpDivider/>
33
+ <div class="flex justify-end">
34
+ <EpBtn
35
+ type="error"
36
+ rounded
37
+ size="small"
38
+ @click="showModal = false">
39
+ {{labelClose}}
40
+ </EpBtn>
41
+ </div>
42
+
43
+ </EpModal>
44
+ <p class="dark:text-black">{{title}}</p>
45
+ </div>
46
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import {computed, defineAsyncComponent} from "vue"
3
+ import { useRenderText } from '../../composables/useRenderText';
4
+ import { useComponent } from "../../composables/useComponent";
5
+ import type { NestedComponents } from "../../types/Component";
6
+
7
+ interface Props{
8
+ media?:NestedComponents;
9
+ text:string;
10
+ }
11
+
12
+ const props = withDefaults(defineProps<Props>(), {
13
+ })
14
+
15
+ const currentRenderComponent = computed(() => {
16
+ if (props.media) {
17
+ const componentToLoad = useComponent(props.media.type);
18
+ return defineAsyncComponent(() => import(`../${componentToLoad.path}/${componentToLoad.name}.vue`));
19
+ }
20
+ return null;
21
+ });
22
+
23
+ </script>
24
+
25
+ <template>
26
+ <div class="flex items-center justify-center gap-1">
27
+ <div class="w-full" v-html="useRenderText(text)"></div>
28
+ <div class="w-full" v-if="currentRenderComponent && media">
29
+ <component
30
+ :is="currentRenderComponent"
31
+ v-bind="{...media.data}"/>
32
+ </div>
33
+ </div>
34
+ </template>
@@ -1,4 +0,0 @@
1
- import { a8 as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { a9 as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { a4 as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { U as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { c as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { d as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { u as f } from "./index-FmXc2ivj.js";
2
- export {
3
- f as default
4
- };