@consumidor-positivo/aurora 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -3
- package/astro/AdBox/index.astro +28 -0
- package/astro/Alert/index.astro +257 -0
- package/astro/BadgeInfo/index.astro +55 -0
- package/astro/BadgeState/index.astro +79 -0
- package/astro/Button/index.astro +11 -3
- package/astro/Card/Container/index.astro +44 -0
- package/astro/Card/Emphasis/index.astro +39 -0
- package/astro/Card/Image/index.astro +26 -0
- package/astro/Card/Root/index.astro +53 -0
- package/astro/Card/Tag/index.astro +26 -0
- package/astro/Chip/index.astro +48 -0
- package/astro/ChipBanner/index.astro +160 -0
- package/astro/Container/index.astro +16 -0
- package/astro/Divider/index.astro +27 -0
- package/astro/Image/index.astro +26 -0
- package/astro/LazyImage/index.astro +55 -0
- package/astro/LinkButton/index.astro +54 -0
- package/astro/Logo/ac/BadgeFullWhite.astro +20 -0
- package/astro/Logo/ac/BadgeWhite.astro +23 -0
- package/astro/Logo/ac/BadgeWhiteStroke.astro +27 -0
- package/astro/Logo/ac/BadgeWhiteStrokeDefault.astro +28 -0
- package/astro/Logo/ac/Badget.astro +24 -0
- package/astro/Logo/ac/Primary.astro +28 -0
- package/astro/Logo/ac/PrimaryFillWhite.astro +28 -0
- package/astro/Logo/ac/PrimaryFullWhite.astro +20 -0
- package/astro/Logo/ac/PrimaryNegative.astro +20 -0
- package/astro/Logo/ac/PrimaryWhite.astro +20 -0
- package/astro/Logo/ac/TertiaryWhite.astro +72 -0
- package/astro/Logo/cp/BadgeWhiteStroke.astro +10 -0
- package/astro/Logo/cp/Badget.astro +14 -0
- package/astro/Logo/cp/PrimaryFillWhite.astro +63 -0
- package/astro/Logo/cp/PrimaryFullWhite.astro +27 -0
- package/astro/Logo/cp/PrimaryLogoWhite.astro +67 -0
- package/astro/Logo/cp/PrimaryNegative.astro +27 -0
- package/astro/Logo/cp/PrimaryWhite.astro +27 -0
- package/astro/Modal/index.astro +213 -0
- package/astro/NotificationsBar/Link/index.astro +70 -0
- package/astro/NotificationsBar/List/index.astro +38 -0
- package/astro/NotificationsBar/index.astro +24 -0
- package/astro/PartnerBanner/index.astro +52 -0
- package/astro/ProfileNav/index.astro +34 -0
- package/astro/ProgressBar/index.astro +70 -0
- package/astro/Skeleton/index.astro +50 -0
- package/astro/SpecialButton/index.astro +331 -0
- package/astro/Spinner/index.astro +75 -0
- package/astro/SubHeader/index.astro +57 -0
- package/astro/Switch/Card/index.astro +69 -0
- package/astro/Switch/Pure/index.astro +47 -0
- package/astro/Tooltip/index.astro +38 -0
- package/astro/form/Checkbox/Field/index.astro +68 -0
- package/astro/form/Checkbox/Group/index.astro +79 -0
- package/astro/form/Datepicker/Calendar/index.astro +53 -0
- package/astro/form/Datepicker/CalendarHeader/index.astro +57 -0
- package/astro/form/Datepicker/Segment/index.astro +53 -0
- package/astro/form/Datepicker/index.astro +756 -0
- package/astro/form/EmailField/index.astro +237 -0
- package/astro/form/Field/ErrorMessage/index.astro +20 -0
- package/astro/form/Field/Input/index.astro +15 -0
- package/astro/form/Field/InputHolder/index.astro +28 -0
- package/astro/form/Field/Label/index.astro +80 -0
- package/astro/form/Field/Message/index.astro +29 -0
- package/astro/form/Field/Root/index.astro +37 -0
- package/astro/form/Field/TextArea/index.astro +69 -0
- package/astro/form/InputField/index.astro +96 -0
- package/astro/form/PasswordField/index.astro +123 -0
- package/astro/form/Radio/Field/index.astro +52 -0
- package/astro/form/Radio/Group/index.astro +78 -0
- package/astro/form/SelectField/index.astro +561 -0
- package/astro/form/TextareaField/index.astro +81 -0
- package/astro/form/TokenField/index.astro +211 -0
- package/astro/tokens/package.json +6 -0
- package/dist/{tokens-C4ypB4bY.js → astro/tokens/index.es.js} +101 -101
- package/dist/astro/tokens/index.es.js.map +1 -0
- package/dist/components/Alert/index.es.js +1 -1
- package/dist/components/BadgeInfo/index.es.js +1 -1
- package/dist/components/BadgeState/index.es.js +1 -1
- package/dist/components/Image/index.es.js +1 -1
- package/dist/components/Spinner/index.es.js +1 -1
- package/dist/components/form/Checkbox/Field/index.es.js +1 -1
- package/dist/components/form/Datepicker/Calendar/index.es.js +2 -2
- package/dist/components/form/Datepicker/CalendarHeader/index.es.js +2 -2
- package/dist/components/form/Datepicker/PortalHolder/index.es.js +1 -1
- package/dist/components/form/Datepicker/Segment/index.es.js +1 -1
- package/dist/components/form/Datepicker/index.es.js +3 -3
- package/dist/components/form/Field/Label/index.es.js +1 -1
- package/dist/components/form/SelectField/index.es.js +1 -1
- package/dist/{index-BcC9liUl.js → index-Bkl5OBIY.js} +3 -3
- package/dist/{index-BcC9liUl.js.map → index-Bkl5OBIY.js.map} +1 -1
- package/dist/{index-CFYmtkje.js → index-CZfMkAoF.js} +2 -2
- package/dist/{index-CFYmtkje.js.map → index-CZfMkAoF.js.map} +1 -1
- package/dist/{index-CeClo_WS.js → index-Cw1KtRQr.js} +2 -2
- package/dist/{index-CeClo_WS.js.map → index-Cw1KtRQr.js.map} +1 -1
- package/dist/main.es.js +101 -101
- package/package.json +7 -1
- package/dist/tokens-C4ypB4bY.js.map +0 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import SubHeader from '../SubHeader/index.astro'
|
|
4
|
+
import IconX from '../icons/default/IconX.astro'
|
|
5
|
+
import '../../dist/components/Modal/styles.css'
|
|
6
|
+
|
|
7
|
+
type ModalLayout = 'default' | 'centralized'
|
|
8
|
+
type ModalLayoutMobile = 'default' | 'centralized' | 'full-screen'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Differences from React:
|
|
12
|
+
* - No `isOpen`/`onClose`. Any element carrying
|
|
13
|
+
* `data-au-modal-toggle="<id>"` toggles this modal, from anywhere on the
|
|
14
|
+
* page. `closeButton` stands for React's `onClose`: it renders the close
|
|
15
|
+
* button (and the SubHeader back button), which close the modal, and lets
|
|
16
|
+
* `closeOnBackdropClick` work. The root emits `au:modalopen` /
|
|
17
|
+
* `au:modalclose` with `{ id }`.
|
|
18
|
+
* - Like React, which renders nothing while closed, the controller takes the
|
|
19
|
+
* closed modal out of the page and puts it back when it opens.
|
|
20
|
+
* - `headerContent` and `content` are the `header` slot and the default slot.
|
|
21
|
+
* - `ariaLabel` is the native `aria-label`.
|
|
22
|
+
* - `handleHelpInfo` becomes `helpButton`: the SubHeader help button carries
|
|
23
|
+
* `data-au-sub-header="help"` for the page's own `<script>`.
|
|
24
|
+
* - React picks the mobile SubHeader with `isMobile()` (max-width 767px) each
|
|
25
|
+
* time it renders. With `layoutMobile="full-screen"`, the SubHeader rides in
|
|
26
|
+
* a `<template>` and the controller makes the same choice on every open.
|
|
27
|
+
* - `portal` moves the modal to `document.body` when the controller runs, the
|
|
28
|
+
* counterpart of a React `createPortal(<Modal />, document.body)`.
|
|
29
|
+
* - Besides the toggles, a `CustomEvent('au:modalcontrol', { detail: { id,
|
|
30
|
+
* open? } })` dispatched on `document` opens (`open: true`), closes
|
|
31
|
+
* (`open: false`) or toggles (no `open`) the modal with that `id`, for
|
|
32
|
+
* components that drive a modal from their own controller.
|
|
33
|
+
*/
|
|
34
|
+
export type Props = HTMLAttributes<'div'> & {
|
|
35
|
+
id: string
|
|
36
|
+
/** Renders the modal already open. */
|
|
37
|
+
open?: boolean
|
|
38
|
+
/**
|
|
39
|
+
* Calls the close (React `onClose`) when the backdrop (area outside the
|
|
40
|
+
* container) is clicked. Needs `closeButton`, as React needs `onClose`.
|
|
41
|
+
*/
|
|
42
|
+
closeOnBackdropClick?: boolean
|
|
43
|
+
/**
|
|
44
|
+
* Renders the close button (and the SubHeader back button). React renders
|
|
45
|
+
* them only when `onClose` is passed.
|
|
46
|
+
*/
|
|
47
|
+
closeButton?: boolean
|
|
48
|
+
layoutMobile?: ModalLayoutMobile
|
|
49
|
+
layoutDesktop?: ModalLayout
|
|
50
|
+
mobileModalTitle?: string
|
|
51
|
+
/** Renders the help button in the mobile full-screen SubHeader. */
|
|
52
|
+
helpButton?: boolean
|
|
53
|
+
/** Moves the modal to `document.body` once the controller runs. */
|
|
54
|
+
portal?: boolean
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const {
|
|
58
|
+
id,
|
|
59
|
+
open = false,
|
|
60
|
+
closeOnBackdropClick = false,
|
|
61
|
+
closeButton = true,
|
|
62
|
+
layoutMobile = 'default',
|
|
63
|
+
layoutDesktop = 'default',
|
|
64
|
+
mobileModalTitle = 'Título',
|
|
65
|
+
helpButton = false,
|
|
66
|
+
portal = false,
|
|
67
|
+
'aria-label': ariaLabel,
|
|
68
|
+
class: className,
|
|
69
|
+
...rest
|
|
70
|
+
} = Astro.props
|
|
71
|
+
|
|
72
|
+
const isFullScreenMobile = layoutMobile === 'full-screen'
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
<div
|
|
76
|
+
id={id}
|
|
77
|
+
class:list={[
|
|
78
|
+
'au-modal',
|
|
79
|
+
open && 'au-modal--is-open',
|
|
80
|
+
isFullScreenMobile && 'au-modal--mobile-full-screen',
|
|
81
|
+
layoutMobile === 'centralized' && 'au-modal--mobile-centralized',
|
|
82
|
+
layoutDesktop === 'centralized' && 'au-modal--desktop-centralized',
|
|
83
|
+
className,
|
|
84
|
+
]}
|
|
85
|
+
role="dialog"
|
|
86
|
+
aria-modal="true"
|
|
87
|
+
aria-label={ariaLabel ?? mobileModalTitle}
|
|
88
|
+
data-element="au-modal"
|
|
89
|
+
data-au-modal-close-on-backdrop={closeButton && closeOnBackdropClick ? 'true' : undefined}
|
|
90
|
+
data-au-modal-portal={portal ? '' : undefined}
|
|
91
|
+
{...rest}>
|
|
92
|
+
<div class="au-modal__container">
|
|
93
|
+
<div class="au-modal__header">
|
|
94
|
+
{
|
|
95
|
+
closeButton && (
|
|
96
|
+
<button class="au-modal__header-close" aria-label="Fechar">
|
|
97
|
+
<IconX class="au-modal__header-close-icon" />
|
|
98
|
+
</button>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
<slot name="header" />
|
|
102
|
+
{
|
|
103
|
+
isFullScreenMobile && (
|
|
104
|
+
<template data-au-modal-mobile-header>
|
|
105
|
+
{closeButton && (
|
|
106
|
+
<SubHeader title={mobileModalTitle} showHelp={helpButton} />
|
|
107
|
+
)}
|
|
108
|
+
</template>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
</div>
|
|
112
|
+
<div class="au-modal__content">
|
|
113
|
+
<slot />
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<script>
|
|
119
|
+
import { elementController } from '@consumidor-positivo/aurora/astro/runtime'
|
|
120
|
+
|
|
121
|
+
const OPEN_CLASS = 'au-modal--is-open'
|
|
122
|
+
// Same rule as `isMobile()` (lib/core/utils/isMobile.ts).
|
|
123
|
+
const MOBILE_QUERY = 'screen and (max-width:767px)'
|
|
124
|
+
|
|
125
|
+
elementController('au-modal', ({ root, on, emit }) => {
|
|
126
|
+
const toggleSelector = `[data-au-modal-toggle="${root.id}"]`
|
|
127
|
+
const closesOnBackdrop = root.dataset.auModalCloseOnBackdrop === 'true'
|
|
128
|
+
root.removeAttribute('data-au-modal-close-on-backdrop')
|
|
129
|
+
|
|
130
|
+
const header = root.querySelector<HTMLElement>(
|
|
131
|
+
':scope > .au-modal__container > .au-modal__header',
|
|
132
|
+
)
|
|
133
|
+
const template = header?.querySelector<HTMLTemplateElement>(
|
|
134
|
+
':scope > template[data-au-modal-mobile-header]',
|
|
135
|
+
)
|
|
136
|
+
// Full-screen mobile: React renders either the close button + header
|
|
137
|
+
// content or the SubHeader, never both.
|
|
138
|
+
const desktopNodes = header
|
|
139
|
+
? Array.from(header.childNodes).filter((node) => node !== template)
|
|
140
|
+
: []
|
|
141
|
+
const mobileNodes = template ? Array.from(template.content.childNodes) : []
|
|
142
|
+
template?.remove()
|
|
143
|
+
|
|
144
|
+
function pickHeader() {
|
|
145
|
+
if (!header || !template) return
|
|
146
|
+
const isMobile = window.matchMedia(MOBILE_QUERY).matches
|
|
147
|
+
const [show, hide] = isMobile
|
|
148
|
+
? [mobileNodes, desktopNodes]
|
|
149
|
+
: [desktopNodes, mobileNodes]
|
|
150
|
+
hide.forEach((node) => node.parentNode === header && header.removeChild(node))
|
|
151
|
+
show.forEach((node) => header.appendChild(node))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// React renders nothing while closed: the closed modal leaves the page
|
|
155
|
+
// and this marker keeps its place.
|
|
156
|
+
const placeholder = document.createComment('au-modal')
|
|
157
|
+
const isOpen = () => root.classList.contains(OPEN_CLASS)
|
|
158
|
+
|
|
159
|
+
function setOpen(open: boolean, silent = false) {
|
|
160
|
+
document
|
|
161
|
+
.querySelectorAll(toggleSelector)
|
|
162
|
+
.forEach((trigger) => trigger.setAttribute('aria-expanded', String(open)))
|
|
163
|
+
|
|
164
|
+
if (open) {
|
|
165
|
+
pickHeader()
|
|
166
|
+
root.classList.add(OPEN_CLASS)
|
|
167
|
+
if (placeholder.parentNode) placeholder.replaceWith(root)
|
|
168
|
+
if (!silent) emit('au:modalopen', { id: root.id })
|
|
169
|
+
return
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
root.classList.remove(OPEN_CLASS)
|
|
173
|
+
// Emitted while still in the page, so the event reaches `document`.
|
|
174
|
+
if (!silent) emit('au:modalclose', { id: root.id })
|
|
175
|
+
if (root.parentNode) root.replaceWith(placeholder)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
document.querySelectorAll(toggleSelector).forEach((trigger) => {
|
|
179
|
+
trigger.setAttribute('aria-controls', root.id)
|
|
180
|
+
})
|
|
181
|
+
// Controller setting only; React's root carries no such attribute.
|
|
182
|
+
if (root.hasAttribute('data-au-modal-portal')) {
|
|
183
|
+
root.removeAttribute('data-au-modal-portal')
|
|
184
|
+
document.body.appendChild(root)
|
|
185
|
+
}
|
|
186
|
+
setOpen(isOpen(), true)
|
|
187
|
+
|
|
188
|
+
on('click', (event) => {
|
|
189
|
+
const target = event.target as Element | null
|
|
190
|
+
// The backdrop is the root itself; the container swallows its own clicks.
|
|
191
|
+
if (target === root) {
|
|
192
|
+
if (closesOnBackdrop) setOpen(false)
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
const close = target?.closest(
|
|
196
|
+
'.au-modal__header-close, .au-sub-header [data-au-sub-header="return"]',
|
|
197
|
+
)
|
|
198
|
+
if (close && header?.contains(close)) setOpen(false)
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
on('global:click', (event) => {
|
|
202
|
+
const trigger = (event.target as Element | null)?.closest(toggleSelector)
|
|
203
|
+
if (!trigger) return
|
|
204
|
+
setOpen(!isOpen())
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
on('global:au:modalcontrol', (event) => {
|
|
208
|
+
const detail = (event as CustomEvent<{ id?: string; open?: boolean }>).detail
|
|
209
|
+
if (!detail || detail.id !== root.id) return
|
|
210
|
+
setOpen(detail.open ?? !isOpen())
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
</script>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import Text from '../../Text/index.astro'
|
|
4
|
+
import '../../../dist/components/NotificationsBar/styles.css'
|
|
5
|
+
|
|
6
|
+
export type NotificationsBarLinkItem = {
|
|
7
|
+
title: string
|
|
8
|
+
createdAt?: string
|
|
9
|
+
isUnread?: boolean
|
|
10
|
+
/** Renders the "Excluir" button (React renders it when `onDelete` is passed). */
|
|
11
|
+
deletable?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `NotificationsBar.Link` in React. No `onClick`/`onDelete`: the item button
|
|
16
|
+
* carries `data-au-notifications-bar="link"` and the delete button
|
|
17
|
+
* `data-au-notifications-bar="delete"`, so the page's own `<script>` can wire
|
|
18
|
+
* them. `Icon` is the `icon` slot.
|
|
19
|
+
*/
|
|
20
|
+
export type Props = Omit<HTMLAttributes<'div'>, 'title'> & NotificationsBarLinkItem
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
title,
|
|
24
|
+
createdAt,
|
|
25
|
+
isUnread = false,
|
|
26
|
+
deletable = false,
|
|
27
|
+
class: className,
|
|
28
|
+
...rest
|
|
29
|
+
} = Astro.props
|
|
30
|
+
|
|
31
|
+
const timestampId = `au-notifications-bar-${crypto.randomUUID().slice(0, 8)}`
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
<div class:list={['au-notifications-bar__item', className]} {...rest}>
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
class="au-notifications-bar__link"
|
|
38
|
+
data-au-notifications-bar="link"
|
|
39
|
+
aria-describedby={createdAt ? timestampId : undefined}>
|
|
40
|
+
{
|
|
41
|
+
Astro.slots.has('icon') && (
|
|
42
|
+
<span aria-hidden="true">
|
|
43
|
+
<slot name="icon" />
|
|
44
|
+
</span>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
<Text as="span" variant="body-medium" weight="regular">
|
|
48
|
+
{isUnread && <span class="au-sr-only">não lida — </span>}
|
|
49
|
+
{title}
|
|
50
|
+
</Text>
|
|
51
|
+
</button>
|
|
52
|
+
<div class="au-notifications-bar__actions">
|
|
53
|
+
<Text as="span" id={timestampId} variant="body-small">
|
|
54
|
+
{createdAt}
|
|
55
|
+
</Text>
|
|
56
|
+
{
|
|
57
|
+
deletable && (
|
|
58
|
+
<button
|
|
59
|
+
type="button"
|
|
60
|
+
class="au-notifications-bar__delete-btn"
|
|
61
|
+
data-au-notifications-bar="delete"
|
|
62
|
+
aria-label={`Excluir: ${title}`}>
|
|
63
|
+
<Text as="span" variant="body-small" weight="semibold">
|
|
64
|
+
Excluir
|
|
65
|
+
</Text>
|
|
66
|
+
</button>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import Text from '../../Text/index.astro'
|
|
4
|
+
import NotificationsBarLink from '../Link/index.astro'
|
|
5
|
+
import type { NotificationsBarLinkItem } from '../Link/index.astro'
|
|
6
|
+
import '../../../dist/components/NotificationsBar/styles.css'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `NotificationsBar.List` in React. `dataSource` + `renderItem` become `data`:
|
|
10
|
+
* the list renders a `NotificationsBar/Link` per item. For custom items (an
|
|
11
|
+
* icon, other markup), put `NotificationsBar/Link`s in the default slot,
|
|
12
|
+
* rendered after `data`.
|
|
13
|
+
*/
|
|
14
|
+
export type Props = Omit<HTMLAttributes<'div'>, 'title'> & {
|
|
15
|
+
title: string
|
|
16
|
+
data?: NotificationsBarLinkItem[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
title,
|
|
21
|
+
data = [],
|
|
22
|
+
class: className,
|
|
23
|
+
// Astro hands a component its own `slot="recents|olds"` as a prop; spread
|
|
24
|
+
// into `...rest` it would render as a stray `slot` attribute.
|
|
25
|
+
slot: _slot,
|
|
26
|
+
...rest
|
|
27
|
+
} = Astro.props
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<div class:list={['au-notifications-bar__section', className]} {...rest}>
|
|
31
|
+
<Text as="h3" variant="body-medium" weight="bold">
|
|
32
|
+
{title}
|
|
33
|
+
</Text>
|
|
34
|
+
<div class="au-notifications-bar__list">
|
|
35
|
+
{data.map((item) => <NotificationsBarLink {...item} />)}
|
|
36
|
+
<slot />
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import '../../dist/components/NotificationsBar/styles.css'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `NotificationsBar.Root` in React. `renderRecents` and `renderOlds` become
|
|
7
|
+
* the `recents` and `olds` slots, rendered in that order (the stylesheet
|
|
8
|
+
* highlights the first section as the unread one). The default slot comes
|
|
9
|
+
* last, for anything else.
|
|
10
|
+
*/
|
|
11
|
+
export type Props = HTMLAttributes<'div'>
|
|
12
|
+
|
|
13
|
+
const { class: className, ...rest } = Astro.props
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class:list={['au-notifications-bar', className]}
|
|
18
|
+
role="region"
|
|
19
|
+
aria-label="Notificações"
|
|
20
|
+
{...rest}>
|
|
21
|
+
<slot name="recents" />
|
|
22
|
+
<slot name="olds" />
|
|
23
|
+
<slot />
|
|
24
|
+
</div>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import Text from '../Text/index.astro'
|
|
4
|
+
import '../../dist/components/PartnerBanner/styles.css'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The React `icon` prop is the `icon` slot (and still adds
|
|
8
|
+
* `au-partner-banner--with-icon`); `ariaLabel` is the plain `aria-label`
|
|
9
|
+
* attribute and `className` the plain `class`. No `onButtonClick`: the button
|
|
10
|
+
* carries `data-au-partner-banner="button"` for the page's own `<script>`.
|
|
11
|
+
* Every HTML attribute is forwarded to the `<aside>`.
|
|
12
|
+
*/
|
|
13
|
+
export type Props = HTMLAttributes<'aside'> & {
|
|
14
|
+
text: string
|
|
15
|
+
btnText: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { text, btnText, class: className, ...rest } = Astro.props
|
|
19
|
+
|
|
20
|
+
const hasIcon = Astro.slots.has('icon')
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<aside
|
|
24
|
+
class:list={[
|
|
25
|
+
'au-partner-banner',
|
|
26
|
+
hasIcon && 'au-partner-banner--with-icon',
|
|
27
|
+
className,
|
|
28
|
+
]}
|
|
29
|
+
{...rest}>
|
|
30
|
+
{
|
|
31
|
+
hasIcon && (
|
|
32
|
+
<div class="au-partner-banner__icon" aria-hidden="true">
|
|
33
|
+
<slot name="icon" />
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
<div class="au-partner-banner__content">
|
|
38
|
+
<Text
|
|
39
|
+
as="p"
|
|
40
|
+
variant="body-small"
|
|
41
|
+
color="secondary"
|
|
42
|
+
class="au-partner-banner__text">
|
|
43
|
+
{text}
|
|
44
|
+
</Text>
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
class="au-partner-banner__button"
|
|
48
|
+
data-au-partner-banner="button">
|
|
49
|
+
<Text as="span" variant="body-small" weight="semibold">{btnText}</Text>
|
|
50
|
+
</button>
|
|
51
|
+
</div>
|
|
52
|
+
</aside>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import Text from '../Text/index.astro'
|
|
4
|
+
import '../../dist/components/ProfileNav/styles.css'
|
|
5
|
+
|
|
6
|
+
/** Same props as React; every HTML attribute is forwarded to the root `div`. */
|
|
7
|
+
export type Props = HTMLAttributes<'div'> & {
|
|
8
|
+
/** Shown in the greeting ("Olá, {name}"). */
|
|
9
|
+
name: string
|
|
10
|
+
/** Source of the two initials in the badge. */
|
|
11
|
+
fullName: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { name, fullName, class: className, ...rest } = Astro.props
|
|
15
|
+
|
|
16
|
+
// Same rule as `lib/core/utils/getInitialLetters.ts`, inlined: a `.astro`
|
|
17
|
+
// ships as source and `lib/core` is not published, so importing it would break
|
|
18
|
+
// in the consumer.
|
|
19
|
+
const initialLetters = fullName
|
|
20
|
+
?.split(' ')
|
|
21
|
+
.map((part) => part[0])
|
|
22
|
+
.slice(0, 2)
|
|
23
|
+
.join('')
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
<div class:list={['au-profile-nav', className]} {...rest}>
|
|
27
|
+
<div class="au-profile-nav__badget">
|
|
28
|
+
<Text variant="heading-small" weight="medium">{initialLetters}</Text>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="div">
|
|
31
|
+
<Text as="h3" variant="heading-micro" weight="bold">Olá, {name}</Text>
|
|
32
|
+
<Text color="secondary">Tudo bem?</Text>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import Text from '../Text/index.astro'
|
|
4
|
+
import '../../dist/components/ProgressBar/styles.css'
|
|
5
|
+
|
|
6
|
+
/** Same props as React; every HTML attribute is forwarded to the root `div`. */
|
|
7
|
+
export type Props = HTMLAttributes<'div'> & {
|
|
8
|
+
/** Shows a continuous bar with a percentage instead of step segments. */
|
|
9
|
+
percentageMode?: boolean
|
|
10
|
+
stepName: string
|
|
11
|
+
currentStep: number
|
|
12
|
+
totalSteps: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
percentageMode = false,
|
|
17
|
+
stepName,
|
|
18
|
+
currentStep,
|
|
19
|
+
totalSteps,
|
|
20
|
+
class: className,
|
|
21
|
+
...rest
|
|
22
|
+
} = Astro.props
|
|
23
|
+
|
|
24
|
+
const safeCurrentStep = Math.max(1, Math.min(currentStep, totalSteps))
|
|
25
|
+
const percentageWidth = (safeCurrentStep / totalSteps) * 100
|
|
26
|
+
const roundedPercentage = Math.round(percentageWidth)
|
|
27
|
+
|
|
28
|
+
const progressText = percentageMode
|
|
29
|
+
? `${roundedPercentage}%`
|
|
30
|
+
: `${safeCurrentStep} de ${totalSteps}`
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
<div
|
|
34
|
+
class:list={['au-progress-bar', className]}
|
|
35
|
+
role="progressbar"
|
|
36
|
+
aria-valuenow={percentageMode ? roundedPercentage : safeCurrentStep}
|
|
37
|
+
aria-valuemin={percentageMode ? 0 : 1}
|
|
38
|
+
aria-valuemax={percentageMode ? 100 : totalSteps}
|
|
39
|
+
aria-label={stepName}
|
|
40
|
+
{...rest}>
|
|
41
|
+
{
|
|
42
|
+
percentageMode ? (
|
|
43
|
+
<div class="au-progress-bar__bar">
|
|
44
|
+
<div
|
|
45
|
+
style={`width: ${percentageWidth}%`}
|
|
46
|
+
class="au-progress-bar__bar-filled"
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
) : (
|
|
50
|
+
<div class="au-progress-bar__steps">
|
|
51
|
+
{Array.from({ length: totalSteps }).map((_, index) => (
|
|
52
|
+
<div class="au-progress-bar__step-container">
|
|
53
|
+
<div
|
|
54
|
+
class:list={[
|
|
55
|
+
'au-progress-bar__step-filled',
|
|
56
|
+
index < safeCurrentStep &&
|
|
57
|
+
'au-progress-bar__step-filled--is-active',
|
|
58
|
+
]}
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
))}
|
|
62
|
+
</div>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
<div class="au-progress-bar__text">
|
|
67
|
+
<Text as="span" variant="body-medium">{stepName}</Text>
|
|
68
|
+
<Text as="span" variant="body-medium">{progressText}</Text>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
import '../../dist/components/Skeleton/styles.css'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Same props as React; every HTML attribute is forwarded to the `div`. The
|
|
7
|
+
* size is an inline `style`, so a `style` passed here is ignored.
|
|
8
|
+
*/
|
|
9
|
+
export type Props = Omit<HTMLAttributes<'div'>, 'color' | 'style'> & {
|
|
10
|
+
active?: boolean
|
|
11
|
+
shape?: 'default' | 'square' | 'circle'
|
|
12
|
+
color?: 'primary' | 'secondary'
|
|
13
|
+
/** Fills the container width when no `width` is given. */
|
|
14
|
+
block?: boolean
|
|
15
|
+
/** Width in px. Defaults to 80px (or 100% with `block`). */
|
|
16
|
+
width?: number
|
|
17
|
+
/** Height in px. Defaults to 28px. */
|
|
18
|
+
height?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
active = true,
|
|
23
|
+
shape = 'default',
|
|
24
|
+
color = 'primary',
|
|
25
|
+
block = false,
|
|
26
|
+
width,
|
|
27
|
+
height,
|
|
28
|
+
class: className,
|
|
29
|
+
...rest
|
|
30
|
+
} = Astro.props
|
|
31
|
+
|
|
32
|
+
const style = {
|
|
33
|
+
height: height ? `${height}px` : '28px',
|
|
34
|
+
width: width ? `${width}px` : block ? '100%' : '80px',
|
|
35
|
+
}
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
<div
|
|
39
|
+
class:list={[
|
|
40
|
+
'au-skeleton',
|
|
41
|
+
active && 'au-skeleton--active',
|
|
42
|
+
shape === 'square' && 'au-skeleton--shape-square',
|
|
43
|
+
shape === 'circle' && 'au-skeleton--shape-circle',
|
|
44
|
+
color === 'secondary' && 'au-skeleton--color-secondary',
|
|
45
|
+
className,
|
|
46
|
+
]}
|
|
47
|
+
aria-hidden="true"
|
|
48
|
+
{...rest}
|
|
49
|
+
style={style}>
|
|
50
|
+
</div>
|