@startlibs/components 1.1.4 → 1.2.0-rc.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 (124) hide show
  1. package/lib/BasicBulletList.mjs +1 -1
  2. package/lib/BasicBulletList.mjs.map +1 -1
  3. package/lib/Button.mjs +3 -3
  4. package/lib/Button.mjs.map +1 -1
  5. package/lib/ContextMenu.mjs +22 -6
  6. package/lib/ContextMenu.mjs.map +1 -1
  7. package/lib/Dialog.mjs +60 -24
  8. package/lib/Dialog.mjs.map +1 -1
  9. package/lib/Icon.mjs +10 -4
  10. package/lib/Icon.mjs.map +1 -1
  11. package/lib/Loading.mjs +26 -3
  12. package/lib/Loading.mjs.map +1 -1
  13. package/lib/PageLoader.mjs +2 -2
  14. package/lib/PageLoader.mjs.map +1 -1
  15. package/lib/PersistentNotifications.mjs +1 -1
  16. package/lib/PersistentNotifications.mjs.map +1 -1
  17. package/lib/SplitColumnsContainer.mjs +77 -6
  18. package/lib/SplitColumnsContainer.mjs.map +1 -1
  19. package/lib/TextButton.mjs +1 -1
  20. package/lib/TextButton.mjs.map +1 -1
  21. package/lib/ToastNotifications.mjs +16 -14
  22. package/lib/ToastNotifications.mjs.map +1 -1
  23. package/lib/alt/dialogs/DialogWithImageHeader.mjs +1 -1
  24. package/lib/alt/dialogs/DialogWithImageHeader.mjs.map +1 -1
  25. package/lib/alt/dialogs/DialogWithSidebar.mjs +7 -3
  26. package/lib/alt/dialogs/DialogWithSidebar.mjs.map +1 -1
  27. package/lib/alt/dialogs/MobileBubbleDialog.mjs +1 -1
  28. package/lib/alt/dialogs/MobileBubbleDialog.mjs.map +1 -1
  29. package/lib/containers/DialogContainer.mjs +29 -10
  30. package/lib/containers/DialogContainer.mjs.map +1 -1
  31. package/lib/index.cjs +286 -93
  32. package/lib/index.cjs.map +1 -1
  33. package/lib/willUseIsSticky.mjs +23 -2
  34. package/lib/willUseIsSticky.mjs.map +1 -1
  35. package/lib-yak/BasicBulletList.mjs +27 -0
  36. package/lib-yak/BasicBulletList.mjs.map +1 -0
  37. package/lib-yak/Button.mjs +374 -0
  38. package/lib-yak/Button.mjs.map +1 -0
  39. package/lib-yak/ContextMenu.mjs +642 -0
  40. package/lib-yak/ContextMenu.mjs.map +1 -0
  41. package/lib-yak/Dialog.mjs +469 -0
  42. package/lib-yak/Dialog.mjs.map +1 -0
  43. package/lib-yak/Draggable.mjs +892 -0
  44. package/lib-yak/Draggable.mjs.map +1 -0
  45. package/lib-yak/ErrorBoundary.mjs +108 -0
  46. package/lib-yak/ErrorBoundary.mjs.map +1 -0
  47. package/lib-yak/FillLastLineResizer.mjs +238 -0
  48. package/lib-yak/FillLastLineResizer.mjs.map +1 -0
  49. package/lib-yak/Flip.mjs +644 -0
  50. package/lib-yak/Flip.mjs.map +1 -0
  51. package/lib-yak/FlipList.mjs +186 -0
  52. package/lib-yak/FlipList.mjs.map +1 -0
  53. package/lib-yak/FormatDate.mjs +25 -0
  54. package/lib-yak/FormatDate.mjs.map +1 -0
  55. package/lib-yak/Icon.mjs +74 -0
  56. package/lib-yak/Icon.mjs.map +1 -0
  57. package/lib-yak/Image.mjs +41 -0
  58. package/lib-yak/Image.mjs.map +1 -0
  59. package/lib-yak/Link.mjs +116 -0
  60. package/lib-yak/Link.mjs.map +1 -0
  61. package/lib-yak/Loading.mjs +54 -0
  62. package/lib-yak/Loading.mjs.map +1 -0
  63. package/lib-yak/LoadingDiv.mjs +82 -0
  64. package/lib-yak/LoadingDiv.mjs.map +1 -0
  65. package/lib-yak/Notifications.mjs +99 -0
  66. package/lib-yak/Notifications.mjs.map +1 -0
  67. package/lib-yak/PageLoader.mjs +61 -0
  68. package/lib-yak/PageLoader.mjs.map +1 -0
  69. package/lib-yak/PersistentNotifications.mjs +209 -0
  70. package/lib-yak/PersistentNotifications.mjs.map +1 -0
  71. package/lib-yak/Popup.mjs +66 -0
  72. package/lib-yak/Popup.mjs.map +1 -0
  73. package/lib-yak/SplitColumnsContainer.mjs +140 -0
  74. package/lib-yak/SplitColumnsContainer.mjs.map +1 -0
  75. package/lib-yak/SwitchDiv.mjs +60 -0
  76. package/lib-yak/SwitchDiv.mjs.map +1 -0
  77. package/lib-yak/TextButton.mjs +61 -0
  78. package/lib-yak/TextButton.mjs.map +1 -0
  79. package/lib-yak/ToastNotifications.mjs +316 -0
  80. package/lib-yak/ToastNotifications.mjs.map +1 -0
  81. package/lib-yak/Tooltip.mjs +176 -0
  82. package/lib-yak/Tooltip.mjs.map +1 -0
  83. package/lib-yak/TransitionDiv.mjs +59 -0
  84. package/lib-yak/TransitionDiv.mjs.map +1 -0
  85. package/lib-yak/WarningDialog.mjs +107 -0
  86. package/lib-yak/WarningDialog.mjs.map +1 -0
  87. package/lib-yak/alt/buttons/OnClickLoadingButton.mjs +36 -0
  88. package/lib-yak/alt/buttons/OnClickLoadingButton.mjs.map +1 -0
  89. package/lib-yak/alt/dialogs/DialogWithImageHeader.mjs +50 -0
  90. package/lib-yak/alt/dialogs/DialogWithImageHeader.mjs.map +1 -0
  91. package/lib-yak/alt/dialogs/DialogWithSidebar.mjs +193 -0
  92. package/lib-yak/alt/dialogs/DialogWithSidebar.mjs.map +1 -0
  93. package/lib-yak/alt/dialogs/MobileBubbleDialog.mjs +82 -0
  94. package/lib-yak/alt/dialogs/MobileBubbleDialog.mjs.map +1 -0
  95. package/lib-yak/containers/DialogContainer.mjs +482 -0
  96. package/lib-yak/containers/DialogContainer.mjs.map +1 -0
  97. package/lib-yak/containers/Reposition.mjs +35 -0
  98. package/lib-yak/containers/Reposition.mjs.map +1 -0
  99. package/lib-yak/containers/usePositioning.mjs +311 -0
  100. package/lib-yak/containers/usePositioning.mjs.map +1 -0
  101. package/lib-yak/index.mjs +37 -0
  102. package/lib-yak/index.mjs.map +1 -0
  103. package/lib-yak/useDialogWithToggle.mjs +18 -0
  104. package/lib-yak/useDialogWithToggle.mjs.map +1 -0
  105. package/lib-yak/willUseIsSticky.mjs +147 -0
  106. package/lib-yak/willUseIsSticky.mjs.map +1 -0
  107. package/package.json +12 -3
  108. package/src/BasicBulletList.jsx +1 -1
  109. package/src/Button.jsx +36 -30
  110. package/src/ContextMenu.jsx +21 -7
  111. package/src/Dialog.jsx +30 -12
  112. package/src/Icon.jsx +5 -4
  113. package/src/Loading.jsx +19 -5
  114. package/src/PageLoader.jsx +3 -3
  115. package/src/PersistentNotifications.jsx +2 -2
  116. package/src/SplitColumnsContainer.jsx +89 -30
  117. package/src/TextButton.jsx +1 -1
  118. package/src/ToastNotifications.jsx +15 -8
  119. package/src/alt/dialogs/DialogWithImageHeader.jsx +2 -2
  120. package/src/alt/dialogs/DialogWithSidebar.jsx +6 -5
  121. package/src/alt/dialogs/MobileBubbleDialog.jsx +1 -1
  122. package/src/containers/DialogContainer.jsx +11 -4
  123. package/src/willUseIsSticky.jsx +22 -2
  124. package/lib/index.js +0 -5444
@@ -0,0 +1,642 @@
1
+ import _defineProperty from '@babel/runtime/helpers/defineProperty';
2
+ import _extends from '@babel/runtime/helpers/extends';
3
+ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
4
+ import { yakDomTag } from '@startlibs/utils/yakDomTag';
5
+ import React, { useRef, useEffect, forwardRef, useState, useMemo } from 'react';
6
+ import ReactDOM from 'react-dom';
7
+ import { styled, css } from '@yak/react';
8
+ import { useEnsureRef, useToggle, useRefState, willUseLayers, willUseSharedState, Fill } from '@startlibs/core';
9
+ import { transparentize, darken } from 'polished';
10
+ import { isMemo } from 'react-is';
11
+ import { oneWayAnimation, animationTiming, getColor, isMobile, callIfFunction, createPressAndMoveEvent, stopPropagation } from '@startlibs/utils';
12
+ import mitt from 'mitt';
13
+ import { Button } from './Button.mjs';
14
+ import { useFlipEnter, useFlipLeave } from './Flip.mjs';
15
+ import { Icon } from './Icon.mjs';
16
+ import { Link } from './Link.mjs';
17
+ import { getDialogLayersSize } from './containers/DialogContainer.mjs';
18
+ import { usePositioning } from './containers/usePositioning.mjs';
19
+
20
+ const _excluded = ["label", "layerIndex", "href", "linkTo", "prefixWith", "subMenu", "icon", "children", "scrollOnHover"],
21
+ _excluded2 = ["emitter", "index", "menuSlot", "keepOpen", "hover", "layerIndex", "hoverCursor", "scrollOnHover", "passTouchThrough", "children", "setCursorOnHover", "onClick", "prefixWith", "linkTo", "icon", "label", "descText", "helpText", "target", "href"],
22
+ _excluded3 = ["children", "sub", "hoverIndex", "autoHover", "menuSlot", "withoutIcons", "onClose", "onHover", "fill", "onClick"],
23
+ _excluded4 = ["slot", "sub", "withoutIcons", "children"];
24
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
25
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
26
+ const fadeIn = oneWayAnimation('opacity: 0', 'opacity: 1');
27
+ const slideDown = oneWayAnimation('transform: translateY(-10px); pointer-events: none', 'transform: translateY(0); pointer-events: none');
28
+ const slideUpOnTop = oneWayAnimation('transform: translateY(10px); pointer-events: none', 'transform: translateY(0); pointer-events: none');
29
+ const slideRight = oneWayAnimation('transform: translateX(-10px)', 'transform: none;');
30
+ const slideLeftOnLeft = oneWayAnimation('transform: translateX(10px); pointer-events: none', 'transform: translateX(0px); pointer-events: none');
31
+ animationTiming('0.2s ease-out');
32
+ const areComponentsEqual = (a, b) => a === b;
33
+
34
+ // Variantes como classe: no yak, o override de theme.startlibs.ListItem não lê props.
35
+ // Sem variante, sem a chave className: o yak sobrescreveria a do app com undefined.
36
+ const ListItem = styled(yakDomTag("li")).attrs(__yakAttrsProps => {
37
+ const __yakAttrs = (__yakAttrsProps => {
38
+ const __yakAttrs = (props => {
39
+ const variants = [props.hover && 'styled-list-item-hover', props.highlight && 'styled-list-item-highlight'].filter(Boolean);
40
+ return variants.length ? {
41
+ className: variants.join(' ')
42
+ } : {};
43
+ })(__yakAttrsProps) || {};
44
+ return Object.assign({}, __yakAttrs, {
45
+ className: __yakAttrs.className ? "styled-theme-list-item " + __yakAttrs.className : "styled-theme-list-item"
46
+ });
47
+ })(__yakAttrsProps) || {};
48
+ return Object.assign({}, __yakAttrs, {
49
+ className: __yakAttrs.className ? "styled-list-item " + __yakAttrs.className : "styled-list-item"
50
+ });
51
+ })`
52
+ position: relative;
53
+ font-size: 13px;
54
+ & > * {
55
+ padding: 11px 1.5rem 11px 3.5rem;
56
+ display: block;
57
+ }
58
+ ${props => props.hasSubmenu && css`
59
+ & > * {
60
+ padding-right: 3rem;
61
+ }
62
+ `}
63
+ ${Icon}, .icon {
64
+ font-size: ${props => props.iconSize || 23}px;
65
+ position: absolute;
66
+ padding-left: 0.25rem;
67
+ left: 0;
68
+ top: 50%;
69
+ transform: translateY(-50%);
70
+ width: 3.5rem;
71
+ text-align: center;
72
+ }
73
+ @media (max-width: 600px) {
74
+ font-size: 15px;
75
+ & > * {
76
+ padding-top: 15px;
77
+ padding-bottom: 15px;
78
+ }
79
+ ${Icon}, .icon {
80
+ font-size: ${props => (props.iconSize || 23) + 2}px;
81
+ }
82
+ }
83
+ & > a {
84
+ color: inherit;
85
+ font-weight: inherit;
86
+ text-decoration: inherit;
87
+ }
88
+ & > a, & > label {
89
+ cursor: pointer;
90
+ }
91
+ ${__yakProps => __yakProps["hover"] && css`
92
+ & > a, & > label {
93
+ background: ${props => transparentize(0.88, getColor("main")(props))};
94
+ color: ${props => darken(0.03, getColor("main")(props))};
95
+ }`}
96
+ ${__yakProps => __yakProps["highlight"] && css`
97
+ color: ${__yakProps => {
98
+ const v = getColor('main');
99
+ return typeof v === 'function' ? v(__yakProps) : v;
100
+ }};
101
+ `}
102
+ input[type="radio"] {
103
+ display: none;
104
+ }
105
+ ${__yakProps => __yakProps["noActions"] && css`
106
+ max-width: 17rem;
107
+ color: rgba(0,0,0,0.4);
108
+ pointer-events: none;
109
+ text-align: center;
110
+ white-space: normal;
111
+ `}
112
+ ${__yakProps => __yakProps["withButton"] && css`
113
+ padding: 0.25rem 1rem;
114
+ ${Button} {
115
+ width: 100%;
116
+ color: white;
117
+ font-weight: 500;
118
+ padding: 10px 1.25rem;
119
+ @media (max-width: 600px) {
120
+ padding: 13px 1.25rem;
121
+ }
122
+ }
123
+ `}
124
+ ${__yakProps => __yakProps["smallPaddingRight"] && css`
125
+ & > * {
126
+ padding-right: 1.5rem;
127
+ }
128
+ `}
129
+
130
+ `;
131
+ const ListItemDescText = styled(yakDomTag("div"))`
132
+ font-size: 11px;
133
+ margin-top: 0.25rem;
134
+ opacity: 0.6;
135
+ @media (max-width: 600px) {
136
+ font-size: 12px;
137
+ }
138
+ `;
139
+ const ListItemHelpText = styled(yakDomTag("span"))`
140
+ opacity: 0.5;
141
+ `;
142
+ const ListMenu = styled(yakDomTag("ul")).attrs({
143
+ className: "styled-list-menu"
144
+ })`
145
+ padding: 0.5rem 0;
146
+ cursor: default;
147
+ overflowY: auto;
148
+ text-align: left;
149
+ color: inherit;
150
+ user-select: none;
151
+ `;
152
+ const ContextListMenu = styled(ListMenu).attrs({
153
+ className: "styled-context-list-menu styled-theme-context-menu"
154
+ })`
155
+ position: absolute;
156
+ z-index: 999;
157
+ background-color: white;
158
+ backdrop-filter: blur(20px);
159
+ background-color: rgb(255 255 255 / 80%);
160
+ box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 10px -2px rgba(0,0,0,0.15), 0 0px 2px 0px rgba(0,0,0,0.2);
161
+ border-radius: 12px;
162
+ margin-bottom: 0.5rem;
163
+ overflow: auto;
164
+ max-height: 100vh;
165
+ max-height: 100dvh;
166
+ max-width: 100vw;
167
+ max-width: 100dvw;
168
+ ${props => props.withoutIcons && css`
169
+ ${ListItem} > * {
170
+ padding-left: 1.5rem;
171
+ }
172
+ `}
173
+ ${__yakProps => __yakProps["sub"] && css`
174
+ ${props => props.fullHeight ? css`` : props.atTop ? css`margin-top: -0.5rem;` : css`margin-top: 0.5rem;`}
175
+
176
+ ${__yakProps => __yakProps["atRight"] ? css`
177
+ margin-left: -4px;
178
+ ` : css`
179
+ margin-left: 4px;
180
+ `}
181
+ `}
182
+
183
+ `;
184
+ const StickyContainer = styled(yakDomTag("div")).attrs({
185
+ className: "styled-sticky-container"
186
+ })`
187
+ position: sticky;
188
+ background: white;
189
+ ${props => props.atBottom && css`
190
+ bottom: -0.5rem;
191
+ padding-bottom: 0.5rem;
192
+ margin-bottom: -0.5rem;
193
+ `}
194
+ ${props => props.atTop && css`
195
+ top: -0.5rem;
196
+ padding-top: 0.5rem;
197
+ margin-top: -0.5rem;
198
+ `}
199
+ `;
200
+ const ListSeparator = styled(yakDomTag("li")).attrs({
201
+ className: "styled-list-separator"
202
+ })`
203
+ border-bottom: 1px solid rgba(0,0,0,0.1);
204
+ margin-top: 0.5rem;
205
+ margin-bottom: 0.5rem;
206
+ cursor: default;
207
+ height: 0;
208
+ ${__yakProps => __yakProps["lighten"] && css`
209
+ border-color: rgba(255,255,255,0.15);
210
+ `}
211
+ `;
212
+ const ListHeading = styled(yakDomTag("li")).attrs({
213
+ className: "styled-list-heading"
214
+ })`
215
+ display: flex;
216
+ align-items: center;
217
+ padding: .5rem 1rem;
218
+ color: rgba(0,0,0,0.4);
219
+ font-size: 12px;
220
+ text-transform: uppercase;
221
+ &:after {
222
+ content: '';
223
+ flex-grow: 1;
224
+ margin-left: 0.75rem;
225
+ height: 1px;
226
+ background: rgba(0,0,0,0.15);
227
+ }
228
+ `;
229
+
230
+ /* No sc, styledExtend(Icon) cria uma identidade própria: o seletor ${Icon} do ListItem
231
+ acima não bate aqui. No yak, styledExtend vira styled(Icon) (plugin, R10) e essa seta
232
+ herda a classe do Icon, então aquele ${Icon} (2 classes, mais específico) passa a
233
+ também valer pra ela, incluindo um "left: 0" que nunca existiu aqui. Com left, right
234
+ e width todos setados o box fica sobreconstrangido e o browser ignora o "right"
235
+ (ganha left+width): a seta migra pra esquerda. !important nas propriedades em comum,
236
+ e left:auto explícito, devolvem o tamanho e a posição próprios nos dois modos. */
237
+ const SubmenuArrowIcon = styled(Icon)`
238
+ font-size: 13px !important;
239
+ position: absolute;
240
+ left: auto !important;
241
+ right: 0;
242
+ top: 50%;
243
+ transform: translateY(-50%);
244
+ width: 3rem !important;
245
+ padding-left: 0 !important;
246
+ text-align: center;
247
+ `;
248
+ class SimpleLi extends React.Component {
249
+ constructor() {
250
+ super(...arguments);
251
+ this.scrollToVisibility = () => {
252
+ const el = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(this);
253
+ const list = el.parentNode;
254
+ if (el.offsetTop < list.scrollTop) {
255
+ list.scrollTop = el.offsetTop;
256
+ } else if (el.offsetTop + el.offsetHeight > list.scrollTop + list.offsetHeight) {
257
+ list.scrollTop = el.offsetTop + el.offsetHeight - list.offsetHeight;
258
+ }
259
+ };
260
+ this.confirm = () => {
261
+ if (this.props.hover) {
262
+ const node = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(this);
263
+ node.click();
264
+ }
265
+ };
266
+ this.onMouseEnter = () => this.props.setCursorOnHover && this.props.setCursorOnHover(this.props.index);
267
+ this.onMouseOut = () => this.props.setCursorOnHover && this.props.setCursorOnHover(-1);
268
+ this.touchEnd = e => {
269
+ if (this.props.children) {
270
+ e.preventDefault();
271
+ if (!this.props.hover) this.onMouseEnter();
272
+ }
273
+ };
274
+ this.onClick = e => {
275
+ this.props.onClick && this.props.onClick();
276
+ };
277
+ }
278
+ componentWillUnmount() {
279
+ this.props.emitter.off('confirm', this.confirm);
280
+ }
281
+ componentDidUpdate() {
282
+ if (this.props.hover && this.props.scrollOnHover !== false) {
283
+ this.scrollToVisibility();
284
+ }
285
+ }
286
+ componentDidMount() {
287
+ this.props.emitter.on('confirm', this.confirm);
288
+ if (this.props.selected && this.props.setCursorOnHover) {
289
+ this.props.setCursorOnHover(this.props.index);
290
+ const el = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.findDOMNode(this);
291
+ const list = el.parentNode;
292
+ list.scrollTop = el.offsetTop + el.offsetHeight / 2 - list.offsetHeight / 2;
293
+ }
294
+ }
295
+ render() {
296
+ const _this$props = this.props,
297
+ {
298
+ label,
299
+ layerIndex,
300
+ href,
301
+ linkTo,
302
+ prefixWith,
303
+ subMenu,
304
+ icon,
305
+ children,
306
+ scrollOnHover
307
+ } = _this$props,
308
+ rest = _objectWithoutProperties(_this$props, _excluded);
309
+ const Tag = linkTo ? Link : 'a';
310
+ return /*#__PURE__*/React.createElement(ListItem, _extends({}, rest, {
311
+ onClick: this.onClick,
312
+ onMouseLeave: this.onMouseOut,
313
+ onMouseEnter: this.onMouseEnter,
314
+ onTouchEnd: this.touchEnd
315
+ }), /*#__PURE__*/React.createElement(Tag, {
316
+ href: href,
317
+ to: linkTo
318
+ }, prefixWith, icon && /*#__PURE__*/React.createElement(Icon, {
319
+ icon: icon
320
+ }), label));
321
+ }
322
+ }
323
+ SimpleLi.isKeyboardNavigable = true;
324
+ SimpleLi.defaultProps = {
325
+ emitter: mitt()
326
+ };
327
+ const Li = /*#__PURE__*/React.forwardRef((_ref, ref) => {
328
+ let {
329
+ emitter = mitt(),
330
+ index,
331
+ menuSlot,
332
+ keepOpen,
333
+ hover,
334
+ layerIndex,
335
+ hoverCursor,
336
+ scrollOnHover,
337
+ passTouchThrough,
338
+ children,
339
+ setCursorOnHover,
340
+ onClick,
341
+ prefixWith,
342
+ linkTo,
343
+ icon,
344
+ label,
345
+ descText,
346
+ helpText,
347
+ target,
348
+ href
349
+ } = _ref,
350
+ rest = _objectWithoutProperties(_ref, _excluded2);
351
+ const nodeRef = useEnsureRef(ref);
352
+ const tagRef = useRef();
353
+ const subMenu = useToggle();
354
+ const subPrevented = useRefState(false);
355
+ const onOpenSub = () => {
356
+ subPrevented.set(false);
357
+ if (hover && children) {
358
+ subMenu.open();
359
+ }
360
+ };
361
+ const onPreventSub = subIndex => {
362
+ if (index !== subIndex) subMenu.close();
363
+ subPrevented.set(true);
364
+ };
365
+ const confirm = () => {
366
+ if (hover) {
367
+ nodeRef.current.click();
368
+ }
369
+ };
370
+ useEffect(() => {
371
+ if (hover && scrollOnHover !== false) {
372
+ try {
373
+ const el = nodeRef.current;
374
+ const parent = el.parentElement;
375
+ const stickyContainer = parent.lastChild;
376
+ const stickyContainerHeight = stickyContainer && stickyContainer.tagName === "DIV" && stickyContainer.offsetTop - parent.scrollTop < parent.offsetHeight ? stickyContainer.offsetHeight : 0;
377
+ if (el.offsetTop > parent.offsetHeight + parent.scrollTop - stickyContainerHeight - el.offsetHeight) {
378
+ parent.scroll(0, el.offsetTop - parent.offsetHeight + el.offsetHeight + stickyContainerHeight);
379
+ } else if (el.offsetTop < parent.scrollTop) {
380
+ parent.scroll(0, el.offsetTop);
381
+ }
382
+ } catch (e) {}
383
+ }
384
+ emitter.on('confirm', confirm);
385
+ emitter.on('preventSub', onPreventSub);
386
+ emitter.on('openSub', onOpenSub);
387
+ return () => {
388
+ emitter.off('confirm', confirm);
389
+ emitter.off('preventSub', onPreventSub);
390
+ emitter.off('openSub', onOpenSub);
391
+ };
392
+ }, [hover]);
393
+ useEffect(() => () => subMenu.close(), []);
394
+ useEffect(() => {
395
+ if (children && !isMobile()) {
396
+ if (hover) {
397
+ if (!subMenu.isOpen || subMenu.closing || !subPrevented.get()) {
398
+ subMenu.open();
399
+ }
400
+ } else {
401
+ if (subMenu.isOpen) {
402
+ if (hoverCursor === -1) {
403
+ // Mouse saiu de todos os itens — provavelmente indo até o submenu (que
404
+ // abre ao lado, com um pequeno gap). Janela generosa; ao alcançá-lo, o
405
+ // onMouseEnter/onMouseMove do submenu chama subMenu.open e cancela.
406
+ subMenu.closeAfter(450);
407
+ } else {
408
+ // Mouse foi para outro item do menu — mantém os 200ms originais.
409
+ subMenu.closeAfter(200);
410
+ }
411
+ emitter.emit('preventSub', index);
412
+ }
413
+ }
414
+ }
415
+ }, [hoverCursor]);
416
+ const onMouseMove = e => {
417
+ if (!hover) {
418
+ callIfFunction(setCursorOnHover, index);
419
+ }
420
+ e === null || e === void 0 || e.stopPropagation();
421
+ };
422
+ const onMouseOut = e => {
423
+ callIfFunction(setCursorOnHover, -1);
424
+ e === null || e === void 0 || e.stopPropagation();
425
+ };
426
+ const onClickHandler = e => {
427
+ if (children || keepOpen) {
428
+ e.stopPropagation();
429
+ }
430
+ if (children) {
431
+ if (hover) {
432
+ subMenu.toggle();
433
+ } else {
434
+ onMouseMove();
435
+ }
436
+ } else {
437
+ callIfFunction(onClick, e);
438
+ }
439
+ };
440
+ const onCloseSub = () => emitter.emit('openSub');
441
+ const addProps = children => React.Children.map(children, c => /*#__PURE__*/React.cloneElement(c, {
442
+ fixed: rest.fixedPosition,
443
+ closing: subMenu.closing,
444
+ onMouseMove: subMenu.open,
445
+ // onMouseEnter não borbulha, então não é barrado pelo stopPropagation dos itens
446
+ // do submenu (linha onMouseMove do Li). Garante que alcançar o submenu sempre
447
+ // cancele o fechamento agendado por closeAfter(200), mantendo-o aberto.
448
+ onMouseEnter: subMenu.open,
449
+ onClose: onCloseSub,
450
+ sub: true,
451
+ slot: c.props.slot || menuSlot
452
+ }));
453
+ const content = /*#__PURE__*/React.createElement(React.Fragment, null, prefixWith, icon && /*#__PURE__*/React.createElement(Icon, {
454
+ icon: icon
455
+ }), label, " ", helpText && /*#__PURE__*/React.createElement(ListItemHelpText, null, "(", helpText, ")"), descText && /*#__PURE__*/React.createElement(ListItemDescText, null, descText), children && /*#__PURE__*/React.createElement(SubmenuArrowIcon, {
456
+ icon: "arrow-right"
457
+ }));
458
+ const Tag = linkTo ? Link : 'a';
459
+ return /*#__PURE__*/React.createElement(ListItem, _extends({
460
+ ref: nodeRef
461
+ }, rest, {
462
+ hover: hover,
463
+ onClick: onClickHandler,
464
+ onMouseLeave: onMouseOut,
465
+ onMouseMove: onMouseMove,
466
+ hasSubmenu: children
467
+ }), rest.withButton || rest.noActions ? content : /*#__PURE__*/React.createElement(Tag, {
468
+ href: href,
469
+ target: target,
470
+ to: linkTo,
471
+ ref: tagRef,
472
+ onMouseEnter: onMouseMove
473
+ }, content), subMenu.isOpen && addProps(children));
474
+ });
475
+ Li.isKeyboardNavigable;
476
+ Li.Simple = SimpleLi;
477
+ const [useContextMenuLayers, contextMenuLayersSize] = willUseLayers();
478
+ const contextMenuLayersQuantity = contextMenuLayersSize;
479
+ const [useContextMenuSharedState] = willUseSharedState();
480
+ const ContextMenuComponent = /*#__PURE__*/forwardRef((_ref2, unesuredRef) => {
481
+ let {
482
+ children,
483
+ sub,
484
+ hoverIndex,
485
+ autoHover,
486
+ menuSlot,
487
+ withoutIcons,
488
+ onClose,
489
+ onHover = () => 0,
490
+ fill,
491
+ onClick
492
+ } = _ref2,
493
+ props = _objectWithoutProperties(_ref2, _excluded3);
494
+ const ref = useEnsureRef(unesuredRef);
495
+ const [hoverCursor, setHoverCursor] = useState(autoHover || sub ? 0 : -1);
496
+ // Hover vindo do mouse não deve rolar a lista: o Chrome dispara mousemove sintético
497
+ // ao fim do scroll, e o item cortado sob o cursor puxaria a lista de volta.
498
+ const hoverFromMouse = useRef(false);
499
+ const [layerCursor, setLayerCursor] = useContextMenuSharedState(0);
500
+ const [layerIndex, {
501
+ getSize
502
+ }] = useContextMenuLayers();
503
+ const itemsEmitter = useMemo(() => mitt(), []);
504
+ useEffect(() => {
505
+ window.addEventListener('keydown', keydown);
506
+ return () => {
507
+ callIfFunction(onClose);
508
+ window.removeEventListener('keydown', keydown);
509
+ };
510
+ }, [layerIndex, layerCursor, hoverCursor]);
511
+ useEffect(() => {
512
+ if (hoverIndex !== undefined) {
513
+ if (hoverIndex !== hoverCursor) hoverFromMouse.current = false;
514
+ setHoverCursor(Math.min(Math.max(hoverIndex, -1), getTotalKeyboardItems(children) + 1));
515
+ }
516
+ }, [hoverIndex !== hoverCursor]);
517
+ const keydown = e => {
518
+ if (e.keyCode === 37 || e.keyCode === 39) {
519
+ if (!e.defaultPrevented) {
520
+ const layers = getSize();
521
+ const direction = e.keyCode - 38;
522
+ setLayerCursor((layerCursor + direction + layers) % layers);
523
+ }
524
+ e.preventDefault();
525
+ }
526
+ if (layerIndex !== layerCursor) return;
527
+ if (e.keyCode === 27 && ref.current) {
528
+ ref.current.click();
529
+ }
530
+ if (e.keyCode === 13 || e.keyCode === 32 && hoverCursor >= 0) {
531
+ // enter
532
+ e.preventDefault();
533
+ itemsEmitter.emit('confirm');
534
+ }
535
+ if (e.keyCode === 38 || e.keyCode === 40) {
536
+ // up down
537
+ e.preventDefault();
538
+ const direction = e.keyCode - 39;
539
+ const max = getTotalKeyboardItems(children);
540
+ const newIndex = (hoverCursor + direction + max) % max;
541
+ hoverFromMouse.current = false;
542
+ setHoverCursor(newIndex);
543
+ onHover(newIndex);
544
+ }
545
+ };
546
+ const getTotalKeyboardItems = children => {
547
+ let sum = 0;
548
+ React.Children.forEach(children, child => {
549
+ if (child && !child.props.disabled && !child.props.readOnly) {
550
+ if (child.type === Li || child.type.isKeyboardNavigable) {
551
+ sum += 1;
552
+ }
553
+ if (areComponentsEqual(child.type, StickyContainer) || child.props.nested) {
554
+ sum += getTotalKeyboardItems(child.props.children);
555
+ }
556
+ }
557
+ });
558
+ return sum;
559
+ };
560
+ const setCursorOnHover = index => {
561
+ hoverFromMouse.current = true;
562
+ setLayerCursor(layerIndex);
563
+ setHoverCursor(index);
564
+ onHover(index);
565
+ };
566
+ const formatChildren = function (children) {
567
+ let indexRef = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
568
+ current: 0
569
+ };
570
+ return React.Children.map(children, (child, j) => child && !child.props.disabled && !child.props.readOnly ? child.props.nested ? /*#__PURE__*/React.cloneElement(child, child.props, formatChildren(child.props.children, indexRef)) : !isMemo(child.type) && areComponentsEqual(child.type, Li) || child.type.isKeyboardNavigable ? /*#__PURE__*/React.cloneElement(child, {
571
+ fixedPosition: props.fixed,
572
+ hover: hoverCursor === indexRef.current && layerIndex === layerCursor,
573
+ hoverCursor: hoverCursor,
574
+ scrollOnHover: !hoverFromMouse.current,
575
+ index: indexRef.current++,
576
+ setCursorOnHover,
577
+ emitter: itemsEmitter,
578
+ layerIndex: layerIndex,
579
+ menuSlot
580
+ }) : areComponentsEqual(child.type, StickyContainer) ? /*#__PURE__*/React.cloneElement(child, _objectSpread(_objectSpread({}, child.props), {}, {
581
+ children: formatChildren(child.props.children, indexRef)
582
+ })) : child : child);
583
+ };
584
+ const touchStart = createPressAndMoveEvent((e, prevPos) => {
585
+ // e.preventDefault()
586
+ e.stopPropagation();
587
+ e.target.dispatchEvent(new MouseEvent('mousemove', {
588
+ bubbles: true
589
+ }));
590
+ return (e, nextPos) => {
591
+ const delta = prevPos.clientY - nextPos.clientY;
592
+ if (Math.abs(delta) > 10) {
593
+ setCursorOnHover(-1);
594
+ }
595
+ };
596
+ });
597
+ return /*#__PURE__*/React.createElement(ContextListMenu, _extends({
598
+ "data-drag": false,
599
+ ref: ref,
600
+ sub: sub,
601
+ onWheel: e => e.stopPropagation(),
602
+ onTouchStart: touchStart,
603
+ withoutIcons: withoutIcons,
604
+ onMouseDown: stopPropagation()
605
+ }, props), formatChildren(children));
606
+ });
607
+ const ContextMenu = /*#__PURE__*/forwardRef((_ref3, ref) => {
608
+ let {
609
+ slot = 'Popup',
610
+ sub,
611
+ withoutIcons,
612
+ children
613
+ } = _ref3,
614
+ rest = _objectWithoutProperties(_ref3, _excluded4);
615
+ const contextMenuRef = useEnsureRef(ref);
616
+ const [positionInfo, placeholder, arrow] = usePositioning(contextMenuRef, rest);
617
+ const {
618
+ atRight,
619
+ atBottom
620
+ } = _objectSpread({}, positionInfo);
621
+ const slotName = useMemo(() => getDialogLayersSize() === 0 ? slot : slot + '-' + (getDialogLayersSize() - 1), []);
622
+ const enterAnimation = useMemo(() => [fadeIn, sub ? atRight ? slideRight : slideLeftOnLeft : atBottom ? slideDown : slideUpOnTop], [atRight, atBottom]);
623
+ useFlipEnter(contextMenuRef, !!positionInfo && enterAnimation);
624
+ useFlipLeave(contextMenuRef, !!positionInfo && enterAnimation, sub && {
625
+ events: {
626
+ mouseover: rest.onMouseMove
627
+ }
628
+ });
629
+ return /*#__PURE__*/React.createElement(React.Fragment, null, placeholder, /*#__PURE__*/React.createElement(Fill, {
630
+ name: slotName
631
+ }, /*#__PURE__*/React.createElement(ContextMenuComponent, _extends({}, rest, {
632
+ menuSlot: slot,
633
+ sub: sub
634
+ }, positionInfo, {
635
+ ref: contextMenuRef,
636
+ withoutIcons: withoutIcons
637
+ }), arrow, children)));
638
+ });
639
+ ContextMenu.ListItem = ListItem;
640
+
641
+ export { ContextListMenu, ContextMenu, ContextMenuComponent, Li, ListHeading, ListItem, ListMenu, ListSeparator, SimpleLi, StickyContainer, contextMenuLayersQuantity };
642
+ //# sourceMappingURL=ContextMenu.mjs.map