5htp-core 0.4.9-99 → 0.5.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "Convenient TypeScript framework designed for Performance and Productivity.",
4
- "version": "0.4.9-99",
4
+ "version": "0.5.0",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -15,6 +15,11 @@ i {
15
15
  text-align: center;
16
16
  font-style: normal;
17
17
 
18
+ // Avoid the flexbox to crush the icon
19
+ .row > & {
20
+ flex: 0 0 1em;
21
+ }
22
+
18
23
  &.spin {
19
24
  animation-name: spin;
20
25
  animation-iteration-count: infinite;
@@ -26,6 +26,10 @@ a {
26
26
  position: relative;
27
27
  }
28
28
  }
29
+
30
+ &.discrete:not(:hover) {
31
+ text-decoration: none;
32
+ }
29
33
  }
30
34
 
31
35
  [contenteditable]:focus {
@@ -6,5 +6,10 @@
6
6
  .bb-1, .bv-1 { border-bottom: solid 1px var(--cLine); }
7
7
  .bl-1, .bh-1 { border-left: solid 1px var(--cLine); }
8
8
 
9
+ .bt-2, .bv-2 { border-top: solid 2px var(--cLine); }
10
+ .br-2, .bh-2 { border-right: solid 2px var(--cLine); }
11
+ .bb-2, .bv-2 { border-bottom: solid 2px var(--cLine); }
12
+ .bl-2, .bh-2 { border-left: solid 1px var(--cLine); }
13
+
9
14
  .b-0 { border: none; }
10
15
  .b-1 { border-top: solid 1px var(--cLine); }
@@ -1,138 +1,129 @@
1
- export type TSide = "left"|"top"|"right"|"bottom";
1
+ export type TSide = "left" | "top" | "right" | "bottom";
2
2
 
3
3
  const debug = false;
4
4
 
5
- export type TPosition = ReturnType<typeof corrigerPosition>
5
+ export type TPosition = ReturnType<typeof corrigerPosition>;
6
6
 
7
7
  export default function corrigerPosition(
8
- conteneur: HTMLElement,
9
- popover: HTMLElement,
10
- absolu: boolean | undefined,
11
- cote: TSide = "bottom",
12
- frame?: HTMLElement
8
+ container: HTMLElement, // button
9
+ popover: HTMLElement, // popover
10
+ preferredSide: TSide = "bottom",
11
+ frame?: HTMLElement // body
13
12
  ) {
14
- // RAPPEL: L'élement sera positionnée relativement à son conteneur
15
- // Tous les calculs ici donnent donc des valeurs relatives au conteneur
16
-
17
- const margeX = 5;
18
- const margeY = 5;
13
+ // Dimensions and bounding rectangles
14
+ const popoverDims = { width: popover.offsetWidth, height: popover.offsetHeight };
15
+ const containerRect = container.getBoundingClientRect();
16
+
17
+ // Find the frame if not provided
18
+ if (!frame) {
19
+ // Find the closest relative-positioned parent
20
+ frame = container.parentElement;
21
+ while (frame && !["relative", "sticky"].includes(getComputedStyle(frame).position)) {
22
+ frame = frame.parentElement;
23
+ }
19
24
 
20
- const dimsPop = {
21
- width: popover.offsetWidth,
22
- height: popover.offsetHeight
25
+ if (!frame) frame = document.body;
23
26
  }
24
27
 
25
- debug && console.log(`[popover] Conteneur =`, conteneur, `Popover =`, popover, `Coté =`, cote);
28
+ if (debug) console.log("frame", frame);
26
29
 
27
- if (dimsPop.width === undefined || dimsPop.height === undefined)
28
- console.error("Unable to get the dimensions of the popover element. Did you pass a react element as content of popover ?");
30
+ const frameRect = frame.getBoundingClientRect();
31
+ const frameOffsetTop = frame.scrollTop;
32
+ const frameOffsetLeft = frame.scrollLeft;
29
33
 
30
- /*----------------------------------
31
- - POSITIONNEMENT INITIAL
32
- ----------------------------------*/
33
- let posInit = {
34
- top: 0,
35
- left: 0
34
+ // Calculate available space in each direction relative to the frame
35
+ const space = {
36
+ top: containerRect.top - frameRect.top,
37
+ bottom: frameRect.bottom - containerRect.bottom,
38
+ left: containerRect.left - frameRect.left,
39
+ right: frameRect.right - containerRect.right,
36
40
  };
37
41
 
38
- // Position & dimensions des élements
39
- const posCont = conteneur.getBoundingClientRect();
40
-
41
- // Placement
42
- debug && console.log(`[popover] Placement = ${cote}`, posCont.height, margeY);
43
- switch (cote) {
44
- case 'top':
45
- posInit.top = -dimsPop.height - margeY;
46
- break;
47
- case 'bottom':
48
- posInit.top = posCont.height + margeY;
49
- break;
50
- case 'left':
51
- posInit.left = -dimsPop.width - margeX;
52
- break;
53
- case 'right':
54
- posInit.left = posCont.width + margeX;
55
- break;
56
- }
57
-
58
- // Centrage Horizontal
59
- if (cote === 'top' || cote === 'bottom') {
60
- debug && console.log(`[popover] Centrage horizontal`);
61
- posInit.left = posCont.width / 2 - dimsPop.width / 2;
62
- }
63
- // Centrage Vertical
64
- if (cote === 'left' || cote === 'right') {
65
- debug && console.log(`[popover] Centrage vertical`);
66
- posInit.top = posCont.height / 2 - dimsPop.height / 2;
67
- }
68
-
69
- /*----------------------------------
70
- - CORRECTION
71
- ----------------------------------*/
72
- let frontieres;
73
- if (frame) { // Via conteneur spécifique
74
- const posFrame = frame.getBoundingClientRect();
75
- frontieres = {
76
- top: Math.max(posFrame.top , 0) + margeY,
77
- left: Math.max(posFrame.left, 0) + margeX,
78
- right: Math.min(posFrame.right, window.innerWidth) - margeX,
79
- bottom: Math.min(posFrame.bottom, window.innerHeight) - margeY
80
- }
81
- } else // Via fenêtre
82
- frontieres = {
83
- top: margeY,
84
- left: margeX,
85
- right: window.innerWidth - margeX,
86
- bottom: window.innerHeight - margeY
42
+ // Helper function to check if there's enough space
43
+ const canFit = (side: TSide) => {
44
+ switch (side) {
45
+ case "top":
46
+ return space.top >= popoverDims.height;
47
+ case "bottom":
48
+ return space.bottom >= popoverDims.height;
49
+ case "left":
50
+ return space.left >= popoverDims.width;
51
+ case "right":
52
+ return space.right >= popoverDims.width;
87
53
  }
88
-
89
- // Position finale de la popover
90
- let posFinale: {
91
- top: string,
92
- left: string,
93
- bottom: string,
94
- right: string
95
- } = {
96
- top: 'auto',
97
- left: 'auto',
98
- right: 'auto',
99
- bottom: 'auto'
100
54
  };
101
55
 
102
- debug && console.log(`[popover] Position initiale =`, posInit, `Frontières =`, frame, '=', frontieres);
103
-
104
- // Extrémité Haut
105
- if (posCont.top + posInit.top < frontieres.top) {
106
- posFinale.top = (frontieres.top - posCont.top) + 'px';
107
- debug && console.log(`[popover] Top: Extremité haut`, posFinale.top);
108
- // Extrémité Bas
109
- } else if (posCont.top + posInit.top + dimsPop.height >= frontieres.bottom) {
110
- posFinale.top = 'auto';
111
- posFinale.bottom = (posCont.bottom - frontieres.bottom) + 'px';
112
- debug && console.log(`[popover] Top: Extremité bas`, posFinale.bottom);
113
- } else {
114
- posFinale.top = posInit.top + 'px';
115
- debug && console.log(`[popover] Top: Conservation`, posFinale.top);
56
+ // Try preferred side first, then fallback
57
+ let side: TSide = preferredSide;
58
+ if (!canFit(preferredSide)) {
59
+ if (canFit("top")) side = "top";
60
+ else if (canFit("bottom")) side = "bottom";
61
+ else if (canFit("left")) side = "left";
62
+ else if (canFit("right")) side = "right";
116
63
  }
117
64
 
118
- // Extrémité Gauche
119
- if (posCont.left + posInit.left < frontieres.left) {
120
- posFinale.left = (frontieres.left - posCont.left) + 'px';
121
- debug && console.log(`[popover] Left: Extremité gauche`, posFinale.left);
122
- // Extrémité Droite
123
- } else if (posCont.left + posInit.left + dimsPop.width >= frontieres.right) {
124
- posFinale.left = 'auto';
125
- posFinale.right = (posCont.right - frontieres.right) + 'px';
126
- debug && console.log(`[popover] Left: Extremité droite`, posFinale.right);
127
- } else {
128
- posFinale.left = posInit.left + 'px';
129
- debug && console.log(`[popover] Left: Conservation`, posFinale.left);
65
+ // Calculate position based on side
66
+ const position = { top: 0, left: 0 };
67
+ if (side === "top") {
68
+ position.top =
69
+ containerRect.top -
70
+ frameRect.top -
71
+ popoverDims.height +
72
+ frameOffsetTop;
73
+ position.left =
74
+ containerRect.left -
75
+ frameRect.left +
76
+ (containerRect.width - popoverDims.width) / 2 +
77
+ frameOffsetLeft;
78
+ } else if (side === "bottom") {
79
+ position.top =
80
+ containerRect.bottom -
81
+ frameRect.top +
82
+ frameOffsetTop;
83
+ position.left =
84
+ containerRect.left -
85
+ frameRect.left +
86
+ (containerRect.width - popoverDims.width) / 2 +
87
+ frameOffsetLeft;
88
+ } else if (side === "left") {
89
+ position.top =
90
+ containerRect.top -
91
+ frameRect.top +
92
+ (containerRect.height - popoverDims.height) / 2 +
93
+ frameOffsetTop;
94
+ position.left =
95
+ containerRect.left -
96
+ frameRect.left -
97
+ popoverDims.width +
98
+ frameOffsetLeft;
99
+ } else if (side === "right") {
100
+ position.top =
101
+ containerRect.top -
102
+ frameRect.top +
103
+ (containerRect.height - popoverDims.height) / 2 +
104
+ frameOffsetTop;
105
+ position.left =
106
+ containerRect.right -
107
+ frameRect.left +
108
+ frameOffsetLeft;
130
109
  }
131
110
 
132
- debug && console.log({ posInit, dimsPop, frontieres }, { posFinale });
133
-
111
+ // Adjust for overflow
112
+ position.top = Math.max(
113
+ frameOffsetTop,
114
+ Math.min(frameRect.height - popoverDims.height + frameOffsetTop, position.top)
115
+ );
116
+ position.left = Math.max(
117
+ frameOffsetLeft,
118
+ Math.min(frameRect.width - popoverDims.width + frameOffsetLeft, position.left)
119
+ );
120
+
121
+ // Return result
134
122
  return {
135
- css: posFinale,
136
- cote: cote
123
+ side,
124
+ css: {
125
+ top: `${position.top}px`,
126
+ left: `${position.left}px`,
127
+ },
137
128
  };
138
129
  }
@@ -47,7 +47,7 @@ export default (props: Props) => {
47
47
 
48
48
  content, state, width, disable,
49
49
 
50
- frame, side,
50
+ frame, side = 'bottom',
51
51
 
52
52
  children, tag,
53
53
 
@@ -72,7 +72,6 @@ export default (props: Props) => {
72
72
  getPosition(
73
73
  refCont.current,
74
74
  refContent.current,
75
- false,
76
75
  side,
77
76
  /*frame || document.getElementById('page') || */undefined
78
77
  )
@@ -137,7 +136,7 @@ export default (props: Props) => {
137
136
  return (
138
137
  <Tag
139
138
  style={{
140
- position: 'relative',
139
+ //position: 'relative',
141
140
  ...(shown ? {
142
141
  zIndex: 11
143
142
  } : {})
@@ -4,6 +4,7 @@
4
4
  // contPopover doit envelopper le bouton sans aucun espace
5
5
  .contPopover {
6
6
  display: inline-block;
7
+ position: static !important; // Allow popvers to go outside of the container which cna be potentially scrollable
7
8
 
8
9
  > .btn {
9
10
  width: 100%;
@@ -32,16 +33,10 @@
32
33
 
33
34
  overflow: auto;
34
35
 
35
- &.pos_bottom { transform: translateY(-1.65rem); }
36
- &.pos_top { transform: translateY(1.65rem); }
37
- &.pos_left { transform: translateX(1.65rem); }
38
- &.pos_right { transform: translateX(-1.65rem); }
39
-
40
36
  top: 100%;
41
37
  max-height: 40rem;
42
38
 
43
39
  min-width: 15rem;
44
- width: 100%;
45
40
  max-width: 90vw;
46
41
 
47
42
  & {
@@ -16,6 +16,7 @@
16
16
  flex-direction: column;
17
17
  gap: 0.5em;
18
18
  align-items: stretch;
19
+ position: relative;
19
20
 
20
21
  > label {
21
22
  font-weight: 700;