@startlibs/components 1.1.5 → 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 (123) 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 +31 -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
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
 
3
- import {getMargin, media} from '@startlibs/utils'
4
- import styled, {css} from 'styled-components'
3
+ import {callIfFunction, getMargin, scrollWidth} from '@startlibs/utils'
4
+ import styled, {useTheme} from 'styled-components'
5
5
 
6
6
  const getMarginFromFieldChild = (props) => {
7
7
  if (!props.last) return 0;
@@ -14,35 +14,94 @@ const getMarginFromFieldChild = (props) => {
14
14
 
15
15
  const splitColumnMargins = {small:0.5,'default':1, big:2}
16
16
 
17
- export const SplitColumnsContainer = styled.div`
18
-
19
- margin-bottom: ${getMarginFromFieldChild}rem;
20
-
21
- ${props => css`
22
- ${media.min(props.viewportMinWidth || 0)`
23
- display: flex;
24
- flex-wrap: nowrap;
25
- margin-left: -${props=>getMargin(splitColumnMargins)(props)/2}rem;
26
- margin-right: -${props=>getMargin(splitColumnMargins)(props)/2}rem;
27
- margin-top: -${props=>getMargin(splitColumnMargins)(props)}rem;
28
- > * {
29
- flex-basis: 0;
30
- flex-grow: 1;
31
- margin-left: ${props=>getMargin(splitColumnMargins)(props)/2}rem;
32
- margin-right: ${props=>getMargin(splitColumnMargins)(props)/2}rem;
33
- margin-top: ${props=>getMargin(splitColumnMargins)(props)}rem;
34
- }
35
- `}
36
- `}
37
- ${props => props.twoColumnsBelowVW && css`
38
- ${media.max(props.twoColumnsBelowVW)`
39
- flex-wrap: wrap;
40
- > * {
41
- flex-basis: 47%;
42
- }
43
- `}
44
- `}
17
+ // viewportMinWidth/twoColumnsBelowVW vêm de props: não tem CSS estático possível pra eles (yak
18
+ // extrai @media em tempo de build, não a partir de uma prop em tempo de render). Troca o
19
+ // `media.min`/`media.max` (que embutiam um `@media` dinâmico) por um hook que ouve
20
+ // `matchMedia` e liga/desliga classe — as duas regras de CSS ficam estáticas, e a mesma soma de
21
+ // `scrollWidth` que `media()` já fazia entra aqui, pro breakpoint bater igual em px (inclusive
22
+ // a 610px, entre 600 e 600 + barra de rolagem).
23
+ const useMatchMedia = (query) => {
24
+ const getMatch = () => (typeof window !== 'undefined' && window.matchMedia) ? window.matchMedia(query).matches : false
25
+ const [matches, setMatches] = React.useState(getMatch)
26
+ React.useEffect(() => {
27
+ if (typeof window === 'undefined' || !window.matchMedia) return
28
+ const mql = window.matchMedia(query)
29
+ const onChange = () => setMatches(mql.matches)
30
+ onChange()
31
+ const addListener = mql.addEventListener ? (cb) => mql.addEventListener('change', cb) : (cb) => mql.addListener(cb)
32
+ const removeListener = mql.removeEventListener ? (cb) => mql.removeEventListener('change', cb) : (cb) => mql.removeListener(cb)
33
+ addListener(onChange)
34
+ return () => removeListener(onChange)
35
+ }, [query])
36
+ return matches
37
+ }
38
+
39
+ // Mesma comparação que checkCustomScreenWidth (utils/src/styled.js) fazia pro theme.overrideMediaWidth:
40
+ // ignora o browser de verdade e compara direto contra o breakpoint (sem somar scrollWidth — o
41
+ // override já é uma largura "combinada", não a viewport física). Usado em testes/impressão.
42
+ const matchesOverrideWidth = (overrideWidth, breakpoint, type) => {
43
+ const currentWidth = callIfFunction(overrideWidth)
44
+ return type === 'min-width' ? currentWidth >= breakpoint : currentWidth <= breakpoint
45
+ }
46
+
47
+ // `breakpoint` null/undefined == bloco original não tinha condição nenhuma pra testar (o `&&`
48
+ // de `props.twoColumnsBelowVW &&`): nem entra no matchMedia, nem no overrideMediaWidth.
49
+ const useBreakpointMatch = (breakpoint, type, overrideWidth) => {
50
+ const hasBreakpoint = breakpoint !== undefined && breakpoint !== null
51
+ const useOverride = hasBreakpoint && overrideWidth !== undefined
52
+ const query = (hasBreakpoint && !useOverride)
53
+ ? `(${type}: ${breakpoint + scrollWidth}px)`
54
+ : 'not all'
55
+ const mediaMatch = useMatchMedia(query)
56
+ if (!hasBreakpoint) return false
57
+ return useOverride ? matchesOverrideWidth(overrideWidth, breakpoint, type) : mediaMatch
58
+ }
59
+
60
+ // styled(Base) mira num componente, não numa tag: ao contrário do antigo styled.div, o
61
+ // styled-components não filtra prop inválida pra <div> nesse caso. Por isso tira aqui, à mão,
62
+ // toda prop que ou é lida só pelo template (margin, last) ou só existe pra decidir a classe
63
+ // aqui dentro (viewportMinWidth, twoColumnsBelowVW), antes de espalhar o resto no elemento real.
64
+ const SplitColumnsContainerBase = React.forwardRef(({viewportMinWidth = 0, twoColumnsBelowVW, margin, last, className, ...rest}, ref) => {
65
+ const overrideWidth = useTheme()?.overrideMediaWidth
66
+ const isFlex = useBreakpointMatch(viewportMinWidth, 'min-width', overrideWidth)
67
+ const isTwoColumns = useBreakpointMatch(twoColumnsBelowVW, 'max-width', overrideWidth)
68
+ const classes = [className, isFlex && 'JS-flex-columns', isTwoColumns && 'JS-two-columns'].filter(Boolean).join(' ')
69
+ return <div ref={ref} className={classes || undefined} {...rest}/>
70
+ })
71
+
72
+ export const SplitColumnsContainer = styled(SplitColumnsContainerBase)`
73
+ margin-bottom: ${props => getMarginFromFieldChild(props)}rem;
74
+
75
+ &.JS-flex-columns {
76
+ display: flex;
77
+ flex-wrap: nowrap;
78
+ /* O yak extrai essas interpolações pra var(--...): um sinal de menos solto no texto estático,
79
+ logo antes da interpolação, vira "-var(--x)" na folha final — sintaxe de CSS inválida
80
+ (margin cai pro valor inicial, 0px). O sinal de menos tem que estar DENTRO do valor
81
+ calculado, não no texto ao redor. */
82
+ margin-left: ${props=> -getMargin(splitColumnMargins)(props)/2}rem;
83
+ margin-right: ${props=> -getMargin(splitColumnMargins)(props)/2}rem;
84
+ margin-top: ${props=> -getMargin(splitColumnMargins)(props)}rem;
85
+ > * {
86
+ flex-basis: 0;
87
+ flex-grow: 1;
88
+ margin-left: ${props=>getMargin(splitColumnMargins)(props)/2}rem;
89
+ margin-right: ${props=>getMargin(splitColumnMargins)(props)/2}rem;
90
+ margin-top: ${props=>getMargin(splitColumnMargins)(props)}rem;
91
+ }
92
+ }
93
+ &.JS-two-columns {
94
+ flex-wrap: wrap;
95
+ > * {
96
+ flex-basis: 47%;
97
+ }
98
+ }
45
99
  `
100
+ // O plugin/babel-plugin-styled-components infere o displayName do nome da variável — mas só
101
+ // quando o import `styled` vem de 'styled-components' (modo sc). No lib-yak o arquivo passa a
102
+ // importar `styled` de '@yak/react' e isso não acontece mais, então fica explícito aqui, nos dois
103
+ // modos: fixDoubledLastMarginBottom precisa do mesmo valor em "SplitColumnsContainer.displayName".
104
+ SplitColumnsContainer.displayName = 'SplitColumnsContainer'
46
105
 
47
106
  export const fixDoubledLastMarginBottom = (children) => {
48
107
  let last = React.Children.count(children)-1
@@ -14,7 +14,7 @@ export const TextButton = styled(({className,isLoading,alert, fontSize, children
14
14
  color: ${props => props.alert ? getColor('alert') : getColor('main')};
15
15
  cursor: pointer;
16
16
  text-decoration: none;
17
- :hover, :active {
17
+ &:hover, &:active {
18
18
  color: ${props => props.alert ? darken(0.1, getColor("alert")(props)) : darken(0.1, getColor("main")(props))};
19
19
  }
20
20
  ${Loading} {
@@ -1,11 +1,10 @@
1
1
  import React, {useEffect, useMemo, useRef} from 'react'
2
2
  import {oneWayAnimation, constrainEvent} from '@startlibs/utils'
3
3
  import _ from 'lodash/fp'
4
- import styled from 'styled-components'
4
+ import styled, {css} from 'styled-components'
5
5
  import {rgba} from 'polished'
6
6
  import {Fill, useToggle, willUseSharedState} from '@startlibs/core'
7
7
  import {getUID, ifUndefined, media, callIfFunction, getColor} from '@startlibs/utils'
8
- import {css} from "styled-components/macro";
9
8
  import {FlipList} from './FlipList'
10
9
  import {Icon} from './Icon'
11
10
  import {Loading} from './Loading'
@@ -27,11 +26,11 @@ const NotificationContainer = styled.div `
27
26
  ${media.mobile`
28
27
  padding-bottom: 0.75rem;
29
28
  `}
30
- ::-webkit-scrollbar {
29
+ &::-webkit-scrollbar {
31
30
  width: 21px;
32
31
  height: 21px;
33
32
  }
34
- ::-webkit-scrollbar-thumb {
33
+ &::-webkit-scrollbar-thumb {
35
34
  pointer-events: all;
36
35
  background: rgba(0,0,0,0.4);
37
36
  border-radius: 100px;
@@ -45,7 +44,7 @@ const NotificationContainer = styled.div `
45
44
  border: 6px solid transparent;
46
45
  }
47
46
  }
48
- ::-webkit-scrollbar-corner {
47
+ &::-webkit-scrollbar-corner {
49
48
  background: transparent;
50
49
  }
51
50
  ${media.desktop`
@@ -68,6 +67,10 @@ const ToastBox = styled.div`
68
67
  margin-top: 0.5rem;
69
68
  overflow: hidden;
70
69
  transition: 0.3s background ease, 0.4s opacity 1.5s;
70
+ /* styled-components (stylis) hoista bloco aninhado de @media para depois do flat; o
71
+ yak preserva a ordem do fonte. Esse fallback sólido precisa vir ANTES dos media
72
+ abaixo, ou o yak aplicaria ele por último (ganhando sempre) nos dois breakpoints. */
73
+ ${props => css`background: ${getColor(props.type)};`}
71
74
  ${media.desktop`
72
75
  background: ${props => rgba(getColor(props.type)(props),ifUndefined(props.opacity,0.7))};
73
76
  max-width: 300px;
@@ -75,7 +78,6 @@ const ToastBox = styled.div`
75
78
  ${media.mobile`
76
79
  background: ${props => rgba(getColor(props.type)(props),ifUndefined(props.opacity,0.8))};
77
80
  `}
78
- ${props => css`background: ${getColor(props.type)};`}
79
81
  `
80
82
  const NotificationTitleContainer = styled.div`
81
83
  background: rgba(0,0,0,0.1);
@@ -103,6 +105,11 @@ const NotificationContent = styled.div`
103
105
  justify-content: center;
104
106
  `}
105
107
  `
108
+ // Task 13c: substitui a prop JSX `css="min-width: 0;"` (R13 proíbe essa forma no yak) por um
109
+ // styled component equivalente.
110
+ const NotificationContentBody = styled.div`
111
+ min-width: 0;
112
+ `
106
113
  const NotificationIconWrapper = styled.div`
107
114
  margin-right: 1rem;
108
115
  position: relative;
@@ -126,7 +133,7 @@ const CloseIcon = styled(Icon).attrs({icon: 'x'})`
126
133
  transform: translateY(-50%);
127
134
  border-radius: 100px;
128
135
  opacity: 0.8;
129
- :hover, :active {
136
+ &:hover, &:active {
130
137
  background: rgba(0,0,0,0.1);
131
138
  opacity: 1;
132
139
  }
@@ -251,7 +258,7 @@ export const ToastNotifications = () => {
251
258
  {notification.isLoading && <Loading size={36} white absolute/>}
252
259
  </NotificationIconWrapper>
253
260
  }
254
- <div css="min-width: 0;">{callIfFunction(notification.content,closeWithLock)}</div>
261
+ <NotificationContentBody>{callIfFunction(notification.content,closeWithLock)}</NotificationContentBody>
255
262
  </NotificationContent>
256
263
  {notification.details &&
257
264
  <NotificationDetails onClick={constrainEvent()}>
@@ -16,10 +16,10 @@ export const DialogWithImageHeader = styled(Dialog)`
16
16
  height: 36px;
17
17
  line-height: 36px;
18
18
  transition: 0.1s ease-out;
19
- :hover {
19
+ &:hover {
20
20
  background-color: rgb(230,230,230);
21
21
  }
22
- :active {
22
+ &:active {
23
23
  background-color: rgb(220,220,220);
24
24
  transition: 0s ease-out;
25
25
  }
@@ -45,7 +45,7 @@ export const DialogTabMenu = styled.ul`
45
45
  ${media.mobile`
46
46
  font-size: 16px;
47
47
  `}
48
- :hover {
48
+ &:hover {
49
49
  background-color: ${getColor('bluishGray')};
50
50
  cursor: pointer;
51
51
  }
@@ -68,7 +68,7 @@ export const DialogTabMenu = styled.ul`
68
68
  ${props => props.menuTabIsOpen && `
69
69
  li {
70
70
  padding: 1.25rem 2rem 1.25rem 3.25rem;
71
- border-radius: 6px
71
+ border-radius: 6px;
72
72
  }
73
73
  .icon{
74
74
  left: 0;
@@ -83,7 +83,7 @@ const fadeOut = [absoluteOnLeave,relativeFadeout]
83
83
  export const MENU_TAB = '$menu$'
84
84
 
85
85
  // ponytail: sem footer — padrão do dialog com barra lateral; fecha pelo X ou por fora
86
- export const DialogWithSidebarPresentation = ({className, tabIsOpen, menuIsOpen, sidebar, Content, openTab, children, title, ...props}) => {
86
+ export const DialogWithSidebarPresentation = ({className, style, tabIsOpen, menuIsOpen, sidebar, Content, openTab, children, title, ...props}) => {
87
87
  const tab = useToggle(tabIsOpen)
88
88
  const sideMenu = usePopupToggle(menuIsOpen)
89
89
  const ref = useRef()
@@ -92,7 +92,7 @@ export const DialogWithSidebarPresentation = ({className, tabIsOpen, menuIsOpen,
92
92
  const menuTabIsOpen = tab.isOpen === MENU_TAB
93
93
 
94
94
  return <DialogContainer {...props} ref={ref}>{({confirmCloseDialog}) =>
95
- <div className={className + " JS-has-wc"} ref={ref}>
95
+ <div className={className + " JS-has-wc"} style={style} ref={ref}>
96
96
  {
97
97
  props.closeDialog &&
98
98
  <CloseIcon onClick={confirmCloseDialog}/>
@@ -123,7 +123,8 @@ const TabContent = ({Content,children,tab,switchAnimation}) => {
123
123
  </div>
124
124
  }
125
125
 
126
- export const DialogWithSidebar = styled((props) => <Dialog fullscreenOnMobile as={DialogWithSidebarPresentation} {...props} />)`
126
+ // R6: "as" não existe no yak. Dialog expõe "tagAs" no lugar (ver Dialog.jsx).
127
+ export const DialogWithSidebar = styled((props) => <Dialog fullscreenOnMobile tagAs={DialogWithSidebarPresentation} {...props} />)`
127
128
  max-width: 59rem;
128
129
  display: flex;
129
130
  padding: 0;
@@ -21,7 +21,7 @@ const MobileBubbleDialogFooter = styled.div `
21
21
  cursor: pointer;
22
22
  border-bottom-left-radius: 10px;
23
23
  border-bottom-right-radius: 10px;
24
- :active {
24
+ &:active {
25
25
  background: rgb(232,232,232);
26
26
  }
27
27
  `
@@ -35,13 +35,20 @@ export const ModalContainer = styled.div`
35
35
  scrollbar-color: transparent transparent;
36
36
  `
37
37
 
38
- const DialogCenter = styled.div`
38
+ // R6: "as" não existe no yak. tagAs troca a tag renderizada (form quando a dialog embute um
39
+ // form, senão div). withScroll/fullscreen/fullscreenOnMobile são lidos pelo template abaixo,
40
+ // mas não são atributos DOM válidos: como o alvo do styled() agora é um componente (não mais
41
+ // styled.div puro), o styled-components para de filtrar prop inválida sozinho — tiram-se à mão
42
+ // antes do spread no elemento real.
43
+ const DialogCenterTagAs = React.forwardRef(({tagAs: Tag = 'div', withScroll, fullscreen, fullscreenOnMobile, ...props}, ref) => <Tag ref={ref} {...props}/>)
44
+
45
+ const DialogCenter = styled(DialogCenterTagAs)`
39
46
  @supports (position:sticky) {
40
47
  will-change: transform, opacity;
41
48
  &.JS-wc-off {
42
49
  will-change: auto;
43
50
  }
44
- }
51
+ }
45
52
  display: -webkit-box;
46
53
  display: -ms-flexbox;
47
54
  display: flex;
@@ -59,7 +66,7 @@ const DialogCenter = styled.div`
59
66
  right:0;
60
67
  align-items: center;
61
68
  ${media.desktop`
62
- padding: ${props => props.fullscreen ? '1rem' : '3rem 0.5rem;'};
69
+ padding: ${props => props.fullscreen ? '1rem' : '3rem 0.5rem'};
63
70
  `}
64
71
  ${media.mobile`
65
72
  padding: ${props => props.fullscreenOnMobile ? '0' : '0.5rem'};
@@ -403,7 +410,7 @@ export const DialogContainer = forwardRef((
403
410
  <AnimatedModal timing={animationTiming} blurBackdrop={blurBackdrop}/>
404
411
  <ModalContainer ref={modal}>
405
412
 
406
- <DialogCenter autoComplete={autoComplete} className="JS-has-wc" withScroll={getSize()>1} fullscreen={fullscreen} fullscreenOnMobile={fullscreenOnMobile} ref={modalScroll} as={usingForm ? 'form' : undefined} onClick={checkClick}
413
+ <DialogCenter autoComplete={autoComplete} className="JS-has-wc" withScroll={getSize()>1} fullscreen={fullscreen} fullscreenOnMobile={fullscreenOnMobile} ref={modalScroll} tagAs={usingForm ? 'form' : undefined} onClick={checkClick}
407
414
  onSubmit={usingForm ? () => {} : undefined}
408
415
  onMouseDown={mouseDown}>
409
416
  {content}
@@ -32,9 +32,29 @@ const SentinelStyle = styled.div`
32
32
  visibility: hidden;
33
33
  height:1px;
34
34
  width: 1px;
35
- ${props => props.addCss}
36
35
  `
37
36
 
37
+ // addCss é texto livre de declarações CSS (ex.: Combobox.jsx em @startlibs/form passa
38
+ // "margin-top:-3px;"), decidido em tempo de execução pelo chamador — não dá pra virar
39
+ // `css\`\`` (precisaria do texto na hora do build) nem ficar como interpolação solta no
40
+ // template (R14: o yak ignora em silêncio uma função que devolve texto livre numa posição de
41
+ // declaração). Vira `style` inline nos dois modos: mesmo resultado visual, sem CSS-in-JS aqui.
42
+ const cssTextToStyle = (text) => {
43
+ const style = {}
44
+ for (const declaration of (text || '').split(';')) {
45
+ const colonIndex = declaration.indexOf(':')
46
+ if (colonIndex === -1) continue
47
+ const property = declaration.slice(0, colonIndex).trim()
48
+ const value = declaration.slice(colonIndex + 1).trim()
49
+ if (!property || !value) continue
50
+ // Custom property (--foo) mantém o nome; o resto vira camelCase (margin-top -> marginTop),
51
+ // igual ao que o React espera num objeto de `style`.
52
+ const camelProperty = property.startsWith('--') ? property : property.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())
53
+ style[camelProperty] = value
54
+ }
55
+ return Object.keys(style).length ? style : undefined
56
+ }
57
+
38
58
  export const willUseIsSticky = (options = {}) => {
39
59
 
40
60
  const [useRegister, onChange] = willUseSharedCallback()
@@ -100,7 +120,7 @@ export const willUseIsSticky = (options = {}) => {
100
120
  }
101
121
  },[])
102
122
 
103
- const renderSentinel = (css = "") => <SentinelStyle addCss={css} className={className} ref={ensuredRef} />
123
+ const renderSentinel = (css = "") => <SentinelStyle style={cssTextToStyle(css)} className={className} ref={ensuredRef} />
104
124
 
105
125
  return children
106
126
  ? children(renderSentinel,isSticky)