@sbkbs/ui 2.0.0-beta.0 → 2.0.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +57 -57
  2. package/dist/assets/favicon/site.webmanifest +21 -21
  3. package/dist/base.css +38 -38
  4. package/dist/components/Accordion/Accordion.js.map +1 -1
  5. package/dist/components/Alert/Alert.js.map +1 -1
  6. package/dist/components/Avatar/Avatar.js.map +1 -1
  7. package/dist/components/Badge/Badge.js.map +1 -1
  8. package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
  9. package/dist/components/Button/Button.js.map +1 -1
  10. package/dist/components/Card/Card.js.map +1 -1
  11. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  12. package/dist/components/Chip/Chip.js.map +1 -1
  13. package/dist/components/Combobox/Combobox.js.map +1 -1
  14. package/dist/components/Divider/Divider.js.map +1 -1
  15. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  16. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  17. package/dist/components/Field/Field.js.map +1 -1
  18. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  19. package/dist/components/Footer/Footer.js.map +1 -1
  20. package/dist/components/GlassPanel/GlassPanel.js.map +1 -1
  21. package/dist/components/Header/Header.js.map +1 -1
  22. package/dist/components/Highlight/Highlight.js.map +1 -1
  23. package/dist/components/Icon/Icon.js.map +1 -1
  24. package/dist/components/IconButton/IconButton.js.map +1 -1
  25. package/dist/components/Input/Input.js.map +1 -1
  26. package/dist/components/Layout/Layout.js.map +1 -1
  27. package/dist/components/Logo/Logo.js.map +1 -1
  28. package/dist/components/MiniCard/MiniCard.js.map +1 -1
  29. package/dist/components/Modal/Modal.js.map +1 -1
  30. package/dist/components/Navigation/Navigation.js.map +1 -1
  31. package/dist/components/NumberInput/NumberInput.js.map +1 -1
  32. package/dist/components/PageHeader/PageHeader.js.map +1 -1
  33. package/dist/components/Pagination/Pagination.js.map +1 -1
  34. package/dist/components/Paragraph/Paragraph.js.map +1 -1
  35. package/dist/components/Popover/Popover.js.map +1 -1
  36. package/dist/components/ProgressBar/ProgressBar.js.map +1 -1
  37. package/dist/components/Radio/Radio.js.map +1 -1
  38. package/dist/components/SectionHeader/SectionHeader.js.map +1 -1
  39. package/dist/components/Select/Select.js.map +1 -1
  40. package/dist/components/SideNav/SideNav.js.map +1 -1
  41. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  42. package/dist/components/Spinner/Spinner.js.map +1 -1
  43. package/dist/components/Stepper/Stepper.js.map +1 -1
  44. package/dist/components/Subtitle/Subtitle.js.map +1 -1
  45. package/dist/components/Switch/Switch.js.map +1 -1
  46. package/dist/components/Table/Table.js.map +1 -1
  47. package/dist/components/Tabs/Tabs.js.map +1 -1
  48. package/dist/components/Tag/Tag.js.map +1 -1
  49. package/dist/components/Textarea/Textarea.js.map +1 -1
  50. package/dist/components/Title/Title.js.map +1 -1
  51. package/dist/components/Toast/Toast.js.map +1 -1
  52. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  53. package/dist/components/Typography/weight.js.map +1 -1
  54. package/dist/fonts.css +8 -8
  55. package/dist/index.cjs.map +1 -1
  56. package/dist/reset.css +9 -9
  57. package/dist/tailwind.css +153 -153
  58. package/dist/theme/ThemeProvider.js.map +1 -1
  59. package/dist/theme/tokens.js.map +1 -1
  60. package/dist/theme.css +327 -327
  61. package/dist/tokens.css +327 -327
  62. package/dist/utils/cn.js.map +1 -1
  63. package/dist/utils/styles.js.map +1 -1
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.js","sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import type React from 'react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { AlertTriangle, CheckCircle2, Info, X, XCircle } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { buttonReset, focusRing } from '../../utils/styles';\n\nexport type ToastTone = 'info' | 'success' | 'warning' | 'error';\n\nexport interface ToastProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Ação opcional (ex.: \"Desfazer\"). */\n action?: { label: string; onClick: () => void };\n description?: React.ReactNode;\n /** Tempo até fechar (ms). 0 mantém aberto. Sobrescreve o padrão do provider. */\n durationMs?: number;\n id?: string;\n onDismiss?: () => void;\n title: React.ReactNode;\n tone?: ToastTone;\n variant?: 'default' | 'glass';\n}\n\nconst TONE: Record<ToastTone, { bar: string; icon: string; Icon: typeof Info }> = {\n info: { bar: 'bg-sbk-info', icon: 'text-sbk-info-fg', Icon: Info },\n success: { bar: 'bg-sbk-success', icon: 'text-sbk-success-fg', Icon: CheckCircle2 },\n warning: { bar: 'bg-sbk-warning', icon: 'text-sbk-warning-fg', Icon: AlertTriangle },\n error: { bar: 'bg-sbk-error', icon: 'text-sbk-error-fg', Icon: XCircle },\n};\n\nexport const Toast = ({\n tone = 'info',\n variant = 'default',\n title,\n description,\n action,\n onDismiss,\n durationMs: _durationMs,\n className,\n ...props\n}: ToastProps) => {\n const { bar, icon, Icon } = TONE[tone];\n const urgent = tone === 'error' || tone === 'warning';\n\n return (\n <div\n aria-atomic=\"true\"\n aria-live={urgent ? 'assertive' : 'polite'}\n className={cn(\n 'relative flex w-[22rem] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sbk-focus focus-visible:outline-solid max-w-[calc(100vw-2rem)] items-start gap-3 overflow-hidden rounded-sbk-sm py-3 pl-4 pr-3 text-sbk-fg animate-sbk-scale-in motion-reduce:animate-none',\n variant === 'glass'\n ? 'sbk-glass sbk-glass-strong'\n : 'border border-sbk-line bg-sbk-surface shadow-sbk-md',\n className,\n )}\n onKeyDown={(e) => e.key === 'Escape' && onDismiss?.()}\n role={urgent ? 'alert' : 'status'}\n tabIndex={0}\n {...props}\n >\n <span aria-hidden=\"true\" className={cn('absolute inset-y-0 left-0 w-1', bar)} />\n <Icon aria-hidden=\"true\" className={cn('mt-0.5 size-5 shrink-0', icon)} strokeWidth={1.75} />\n <div className=\"grid min-w-0 flex-1 gap-0.5\">\n <p className=\"m-0 text-sm font-semibold text-sbk-fg-heading\">{title}</p>\n {description && <p className=\"m-0 text-sm font-light text-sbk-fg-muted\">{description}</p>}\n {action && (\n <button\n className={cn(\n buttonReset,\n 'mt-1 w-fit cursor-pointer text-sm font-semibold text-sbk-primary underline-offset-4 hover:underline',\n focusRing,\n )}\n onClick={action.onClick}\n type=\"button\"\n >\n {action.label}\n </button>\n )}\n </div>\n {onDismiss && (\n <button\n aria-label=\"Fechar notificação\"\n className={cn(\n buttonReset,\n 'inline-flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-sbk-xs text-sbk-fg-muted hover:bg-sbk-surface-hover hover:text-sbk-fg',\n focusRing,\n )}\n onClick={onDismiss}\n type=\"button\"\n >\n <X aria-hidden=\"true\" className=\"size-4\" />\n </button>\n )}\n </div>\n );\n};\nToast.displayName = 'Toast';\n\ntype ToastInput = Omit<ToastProps, 'id'> & { id?: string };\ntype ToastItem = ToastProps & { id: string };\n\ninterface ToastContextValue {\n dismissToast: (id: string) => void;\n /** Adiciona um toast e retorna o id. */\n pushToast: (toast: ToastInput) => string;\n toasts: ToastItem[];\n}\n\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\n\nexport type ToastPosition =\n | 'top-right'\n | 'top-center'\n | 'bottom-right'\n | 'bottom-center'\n | 'bottom-left';\n\nexport interface ToastProviderProps {\n children: React.ReactNode;\n /** Duração padrão (ms). Padrão: 5000. */\n durationMs?: number;\n /** Quantidade máxima visível; os mais antigos saem primeiro. Padrão: 4. */\n max?: number;\n position?: ToastPosition;\n}\n\nlet toastCounter = 0;\n\nexport const ToastProvider = ({\n children,\n durationMs = 5000,\n max = 4,\n position = 'bottom-right',\n}: ToastProviderProps) => {\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n const timers = useRef(new Map<string, ReturnType<typeof setTimeout>>());\n\n const dismissToast = useCallback((id: string) => {\n clearTimeout(timers.current.get(id));\n timers.current.delete(id);\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, []);\n\n const schedule = useCallback(\n (id: string, ms: number) => {\n if (ms > 0)\n timers.current.set(\n id,\n setTimeout(() => dismissToast(id), ms),\n );\n },\n [dismissToast],\n );\n\n const pushToast = useCallback(\n (toast: ToastInput) => {\n const id = toast.id ?? `sbk-toast-${++toastCounter}`;\n setToasts((prev) => [...prev.filter((t) => t.id !== id), { ...toast, id }].slice(-max));\n schedule(id, toast.durationMs ?? durationMs);\n return id;\n },\n [durationMs, max, schedule],\n );\n\n useEffect(() => {\n const map = timers.current;\n return () => {\n map.forEach(clearTimeout);\n map.clear();\n };\n }, []);\n\n /** Pausa os timers enquanto o usuário interage (WCAG 2.2.1). */\n const pause = () => {\n timers.current.forEach(clearTimeout);\n timers.current.clear();\n };\n const resume = () => toasts.forEach((t) => schedule(t.id, t.durationMs ?? durationMs));\n\n const value = useMemo(\n () => ({ toasts, pushToast, dismissToast }),\n [toasts, pushToast, dismissToast],\n );\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n <ToastViewport onPause={pause} onResume={resume} position={position} />\n </ToastContext.Provider>\n );\n};\n\nexport const useToast = (): ToastContextValue => {\n const context = useContext(ToastContext);\n if (!context) throw new Error('useToast deve ser usado dentro de ToastProvider');\n return context;\n};\n\nconst POSITION: Record<ToastPosition, string> = {\n 'top-right': 'top-4 right-4',\n 'top-center': 'top-4 left-1/2 -translate-x-1/2',\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2',\n 'bottom-left': 'bottom-4 left-4',\n};\n\nexport interface ToastViewportProps {\n onPause?: () => void;\n onResume?: () => void;\n position?: ToastPosition;\n}\n\nexport const ToastViewport = ({\n position = 'bottom-right',\n onPause,\n onResume,\n}: ToastViewportProps) => {\n const context = useContext(ToastContext);\n if (!context || context.toasts.length === 0) return null;\n return (\n <section\n aria-label=\"Notificações\"\n className={cn(\n 'pointer-events-none fixed z-[var(--sbk-z-toast)] grid gap-2',\n POSITION[position],\n )}\n onBlur={onResume}\n onFocus={onPause}\n onMouseEnter={onPause}\n onMouseLeave={onResume}\n >\n {context.toasts.map((toast) => (\n <Toast\n key={toast.id}\n {...toast}\n className=\"pointer-events-auto\"\n onDismiss={() => context.dismissToast(toast.id)}\n />\n ))}\n </section>\n );\n};\nToastViewport.displayName = 'ToastViewport';\n"],"names":["TONE","Info","CheckCircle2","AlertTriangle","XCircle","Toast","tone","variant","title","description","action","onDismiss","_durationMs","className","props","bar","icon","Icon","urgent","jsxs","cn","jsx","buttonReset","focusRing","X","ToastContext","createContext","toastCounter","ToastProvider","children","durationMs","max","position","toasts","setToasts","useState","timers","useRef","dismissToast","useCallback","id","prev","t","schedule","ms","pushToast","toast","useEffect","map","pause","resume","value","useMemo","ToastViewport","useToast","context","useContext","POSITION","onPause","onResume"],"mappings":"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"}
1
+ {"version":3,"file":"Toast.js","sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import type React from 'react';\r\nimport {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\nimport { AlertTriangle, CheckCircle2, Info, X, XCircle } from 'lucide-react';\r\nimport { cn } from '../../utils/cn';\r\nimport { buttonReset, focusRing } from '../../utils/styles';\r\n\r\nexport type ToastTone = 'info' | 'success' | 'warning' | 'error';\r\n\r\nexport interface ToastProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\r\n /** Ação opcional (ex.: \"Desfazer\"). */\r\n action?: { label: string; onClick: () => void };\r\n description?: React.ReactNode;\r\n /** Tempo até fechar (ms). 0 mantém aberto. Sobrescreve o padrão do provider. */\r\n durationMs?: number;\r\n id?: string;\r\n onDismiss?: () => void;\r\n title: React.ReactNode;\r\n tone?: ToastTone;\r\n variant?: 'default' | 'glass';\r\n}\r\n\r\nconst TONE: Record<ToastTone, { bar: string; icon: string; Icon: typeof Info }> = {\r\n info: { bar: 'bg-sbk-info', icon: 'text-sbk-info-fg', Icon: Info },\r\n success: { bar: 'bg-sbk-success', icon: 'text-sbk-success-fg', Icon: CheckCircle2 },\r\n warning: { bar: 'bg-sbk-warning', icon: 'text-sbk-warning-fg', Icon: AlertTriangle },\r\n error: { bar: 'bg-sbk-error', icon: 'text-sbk-error-fg', Icon: XCircle },\r\n};\r\n\r\nexport const Toast = ({\r\n tone = 'info',\r\n variant = 'default',\r\n title,\r\n description,\r\n action,\r\n onDismiss,\r\n durationMs: _durationMs,\r\n className,\r\n ...props\r\n}: ToastProps) => {\r\n const { bar, icon, Icon } = TONE[tone];\r\n const urgent = tone === 'error' || tone === 'warning';\r\n\r\n return (\r\n <div\r\n aria-atomic=\"true\"\r\n aria-live={urgent ? 'assertive' : 'polite'}\r\n className={cn(\r\n 'relative flex w-[22rem] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sbk-focus focus-visible:outline-solid max-w-[calc(100vw-2rem)] items-start gap-3 overflow-hidden rounded-sbk-sm py-3 pl-4 pr-3 text-sbk-fg animate-sbk-scale-in motion-reduce:animate-none',\r\n variant === 'glass'\r\n ? 'sbk-glass sbk-glass-strong'\r\n : 'border border-sbk-line bg-sbk-surface shadow-sbk-md',\r\n className,\r\n )}\r\n onKeyDown={(e) => e.key === 'Escape' && onDismiss?.()}\r\n role={urgent ? 'alert' : 'status'}\r\n tabIndex={0}\r\n {...props}\r\n >\r\n <span aria-hidden=\"true\" className={cn('absolute inset-y-0 left-0 w-1', bar)} />\r\n <Icon aria-hidden=\"true\" className={cn('mt-0.5 size-5 shrink-0', icon)} strokeWidth={1.75} />\r\n <div className=\"grid min-w-0 flex-1 gap-0.5\">\r\n <p className=\"m-0 text-sm font-semibold text-sbk-fg-heading\">{title}</p>\r\n {description && <p className=\"m-0 text-sm font-light text-sbk-fg-muted\">{description}</p>}\r\n {action && (\r\n <button\r\n className={cn(\r\n buttonReset,\r\n 'mt-1 w-fit cursor-pointer text-sm font-semibold text-sbk-primary underline-offset-4 hover:underline',\r\n focusRing,\r\n )}\r\n onClick={action.onClick}\r\n type=\"button\"\r\n >\r\n {action.label}\r\n </button>\r\n )}\r\n </div>\r\n {onDismiss && (\r\n <button\r\n aria-label=\"Fechar notificação\"\r\n className={cn(\r\n buttonReset,\r\n 'inline-flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-sbk-xs text-sbk-fg-muted hover:bg-sbk-surface-hover hover:text-sbk-fg',\r\n focusRing,\r\n )}\r\n onClick={onDismiss}\r\n type=\"button\"\r\n >\r\n <X aria-hidden=\"true\" className=\"size-4\" />\r\n </button>\r\n )}\r\n </div>\r\n );\r\n};\r\nToast.displayName = 'Toast';\r\n\r\ntype ToastInput = Omit<ToastProps, 'id'> & { id?: string };\r\ntype ToastItem = ToastProps & { id: string };\r\n\r\ninterface ToastContextValue {\r\n dismissToast: (id: string) => void;\r\n /** Adiciona um toast e retorna o id. */\r\n pushToast: (toast: ToastInput) => string;\r\n toasts: ToastItem[];\r\n}\r\n\r\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\r\n\r\nexport type ToastPosition =\r\n | 'top-right'\r\n | 'top-center'\r\n | 'bottom-right'\r\n | 'bottom-center'\r\n | 'bottom-left';\r\n\r\nexport interface ToastProviderProps {\r\n children: React.ReactNode;\r\n /** Duração padrão (ms). Padrão: 5000. */\r\n durationMs?: number;\r\n /** Quantidade máxima visível; os mais antigos saem primeiro. Padrão: 4. */\r\n max?: number;\r\n position?: ToastPosition;\r\n}\r\n\r\nlet toastCounter = 0;\r\n\r\nexport const ToastProvider = ({\r\n children,\r\n durationMs = 5000,\r\n max = 4,\r\n position = 'bottom-right',\r\n}: ToastProviderProps) => {\r\n const [toasts, setToasts] = useState<ToastItem[]>([]);\r\n const timers = useRef(new Map<string, ReturnType<typeof setTimeout>>());\r\n\r\n const dismissToast = useCallback((id: string) => {\r\n clearTimeout(timers.current.get(id));\r\n timers.current.delete(id);\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n }, []);\r\n\r\n const schedule = useCallback(\r\n (id: string, ms: number) => {\r\n if (ms > 0)\r\n timers.current.set(\r\n id,\r\n setTimeout(() => dismissToast(id), ms),\r\n );\r\n },\r\n [dismissToast],\r\n );\r\n\r\n const pushToast = useCallback(\r\n (toast: ToastInput) => {\r\n const id = toast.id ?? `sbk-toast-${++toastCounter}`;\r\n setToasts((prev) => [...prev.filter((t) => t.id !== id), { ...toast, id }].slice(-max));\r\n schedule(id, toast.durationMs ?? durationMs);\r\n return id;\r\n },\r\n [durationMs, max, schedule],\r\n );\r\n\r\n useEffect(() => {\r\n const map = timers.current;\r\n return () => {\r\n map.forEach(clearTimeout);\r\n map.clear();\r\n };\r\n }, []);\r\n\r\n /** Pausa os timers enquanto o usuário interage (WCAG 2.2.1). */\r\n const pause = () => {\r\n timers.current.forEach(clearTimeout);\r\n timers.current.clear();\r\n };\r\n const resume = () => toasts.forEach((t) => schedule(t.id, t.durationMs ?? durationMs));\r\n\r\n const value = useMemo(\r\n () => ({ toasts, pushToast, dismissToast }),\r\n [toasts, pushToast, dismissToast],\r\n );\r\n\r\n return (\r\n <ToastContext.Provider value={value}>\r\n {children}\r\n <ToastViewport onPause={pause} onResume={resume} position={position} />\r\n </ToastContext.Provider>\r\n );\r\n};\r\n\r\nexport const useToast = (): ToastContextValue => {\r\n const context = useContext(ToastContext);\r\n if (!context) throw new Error('useToast deve ser usado dentro de ToastProvider');\r\n return context;\r\n};\r\n\r\nconst POSITION: Record<ToastPosition, string> = {\r\n 'top-right': 'top-4 right-4',\r\n 'top-center': 'top-4 left-1/2 -translate-x-1/2',\r\n 'bottom-right': 'bottom-4 right-4',\r\n 'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2',\r\n 'bottom-left': 'bottom-4 left-4',\r\n};\r\n\r\nexport interface ToastViewportProps {\r\n onPause?: () => void;\r\n onResume?: () => void;\r\n position?: ToastPosition;\r\n}\r\n\r\nexport const ToastViewport = ({\r\n position = 'bottom-right',\r\n onPause,\r\n onResume,\r\n}: ToastViewportProps) => {\r\n const context = useContext(ToastContext);\r\n if (!context || context.toasts.length === 0) return null;\r\n return (\r\n <section\r\n aria-label=\"Notificações\"\r\n className={cn(\r\n 'pointer-events-none fixed z-[var(--sbk-z-toast)] grid gap-2',\r\n POSITION[position],\r\n )}\r\n onBlur={onResume}\r\n onFocus={onPause}\r\n onMouseEnter={onPause}\r\n onMouseLeave={onResume}\r\n >\r\n {context.toasts.map((toast) => (\r\n <Toast\r\n key={toast.id}\r\n {...toast}\r\n className=\"pointer-events-auto\"\r\n onDismiss={() => context.dismissToast(toast.id)}\r\n />\r\n ))}\r\n </section>\r\n );\r\n};\r\nToastViewport.displayName = 'ToastViewport';\r\n"],"names":["TONE","Info","CheckCircle2","AlertTriangle","XCircle","Toast","tone","variant","title","description","action","onDismiss","_durationMs","className","props","bar","icon","Icon","urgent","jsxs","cn","jsx","buttonReset","focusRing","X","ToastContext","createContext","toastCounter","ToastProvider","children","durationMs","max","position","toasts","setToasts","useState","timers","useRef","dismissToast","useCallback","id","prev","t","schedule","ms","pushToast","toast","useEffect","map","pause","resume","value","useMemo","ToastViewport","useToast","context","useContext","POSITION","onPause","onResume"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import type React from 'react';\nimport { cloneElement, isValidElement, useEffect, useId, useRef, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface TooltipProps {\n /** Elemento focável que dispara o tooltip (botão, link). Texto puro recebe tabIndex=0. */\n children: React.ReactNode;\n content: React.ReactNode;\n /** Atraso para abrir no hover, em ms. Padrão: 150. */\n delay?: number;\n side?: 'top' | 'bottom' | 'left' | 'right';\n}\n\nconst SIDE_CLASS: Record<NonNullable<TooltipProps['side']>, string> = {\n top: 'bottom-full left-1/2 mb-2 -translate-x-1/2',\n bottom: 'top-full left-1/2 mt-2 -translate-x-1/2',\n left: 'right-full top-1/2 mr-2 -translate-y-1/2',\n right: 'left-full top-1/2 ml-2 -translate-y-1/2',\n};\n\n/**\n * Dica contextual em hover e foco (WCAG 1.4.13: dispensável com Esc, persistente enquanto hover).\n * Não use para informação crítica: ela precisa estar visível na tela.\n */\nexport const Tooltip = ({ children, content, side = 'top', delay = 150 }: TooltipProps) => {\n const [open, setOpen] = useState(false);\n const tooltipId = useId();\n const timer = useRef<ReturnType<typeof setTimeout>>();\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => e.key === 'Escape' && setOpen(false);\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [open]);\n\n const show = (withDelay: boolean) => {\n clearTimeout(timer.current);\n if (withDelay) timer.current = setTimeout(() => setOpen(true), delay);\n else setOpen(true);\n };\n const hide = () => {\n clearTimeout(timer.current);\n setOpen(false);\n };\n\n const trigger = isValidElement<Record<string, unknown>>(children) ? (\n cloneElement(children, { 'aria-describedby': tooltipId })\n ) : (\n <span aria-describedby={tooltipId} tabIndex={0}>\n {children}\n </span>\n );\n\n return (\n <span\n className=\"relative inline-flex\"\n onBlur={hide}\n onFocus={() => show(false)}\n onMouseEnter={() => show(true)}\n onMouseLeave={hide}\n >\n {trigger}\n <span\n aria-hidden={!open}\n className={cn(\n 'pointer-events-none absolute z-[var(--sbk-z-tooltip)] w-max max-w-64 rounded-sbk-xs bg-sbk-surface-inverse px-2.5 py-1.5 text-xs font-light text-sbk-fg-inverse shadow-sbk-sm',\n 'transition-opacity duration-150 motion-reduce:transition-none',\n open ? 'visible opacity-100' : 'invisible opacity-0',\n SIDE_CLASS[side],\n )}\n id={tooltipId}\n role=\"tooltip\"\n >\n {content}\n </span>\n </span>\n );\n};\n\nTooltip.displayName = 'Tooltip';\n"],"names":["SIDE_CLASS","Tooltip","children","content","side","delay","open","setOpen","useState","tooltipId","useId","timer","useRef","useEffect","onKey","e","show","withDelay","hide","trigger","isValidElement","cloneElement","jsx","jsxs","cn"],"mappings":";;;AAaA,MAAMA,IAAgE;AAAA,EACpE,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AACT,GAMaC,IAAU,CAAC,EAAE,UAAAC,GAAU,SAAAC,GAAS,MAAAC,IAAO,OAAO,OAAAC,IAAQ,UAAwB;AACzF,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChCC,IAAYC,EAAA,GACZC,IAAQC,EAAA;AAEd,EAAAC,EAAU,MAAM,MAAM,aAAaF,EAAM,OAAO,GAAG,CAAA,CAAE,GAErDE,EAAU,MAAM;AACd,QAAI,CAACP,EAAM;AACX,UAAMQ,IAAQ,CAACC,MAAqBA,EAAE,QAAQ,YAAYR,EAAQ,EAAK;AACvE,oBAAS,iBAAiB,WAAWO,CAAK,GACnC,MAAM,SAAS,oBAAoB,WAAWA,CAAK;AAAA,EAC5D,GAAG,CAACR,CAAI,CAAC;AAET,QAAMU,IAAO,CAACC,MAAuB;AACnC,iBAAaN,EAAM,OAAO,GACtBM,MAAiB,UAAU,WAAW,MAAMV,EAAQ,EAAI,GAAGF,CAAK,MACvD,EAAI;AAAA,EACnB,GACMa,IAAO,MAAM;AACjB,iBAAaP,EAAM,OAAO,GAC1BJ,EAAQ,EAAK;AAAA,EACf,GAEMY,IAAUC,EAAwClB,CAAQ,IAC9DmB,EAAanB,GAAU,EAAE,oBAAoBO,EAAA,CAAW,IAExD,gBAAAa,EAAC,QAAA,EAAK,oBAAkBb,GAAW,UAAU,GAC1C,UAAAP,GACH;AAGF,SACE,gBAAAqB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,QAAQL;AAAA,MACR,SAAS,MAAMF,EAAK,EAAK;AAAA,MACzB,cAAc,MAAMA,EAAK,EAAI;AAAA,MAC7B,cAAcE;AAAA,MAEb,UAAA;AAAA,QAAAC;AAAA,QACD,gBAAAG;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,eAAa,CAAChB;AAAA,YACd,WAAWkB;AAAA,cACT;AAAA,cACA;AAAA,cACAlB,IAAO,wBAAwB;AAAA,cAC/BN,EAAWI,CAAI;AAAA,YAAA;AAAA,YAEjB,IAAIK;AAAA,YACJ,MAAK;AAAA,YAEJ,UAAAN;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAGN;AAEAF,EAAQ,cAAc;"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import type React from 'react';\r\nimport { cloneElement, isValidElement, useEffect, useId, useRef, useState } from 'react';\r\nimport { cn } from '../../utils/cn';\r\n\r\nexport interface TooltipProps {\r\n /** Elemento focável que dispara o tooltip (botão, link). Texto puro recebe tabIndex=0. */\r\n children: React.ReactNode;\r\n content: React.ReactNode;\r\n /** Atraso para abrir no hover, em ms. Padrão: 150. */\r\n delay?: number;\r\n side?: 'top' | 'bottom' | 'left' | 'right';\r\n}\r\n\r\nconst SIDE_CLASS: Record<NonNullable<TooltipProps['side']>, string> = {\r\n top: 'bottom-full left-1/2 mb-2 -translate-x-1/2',\r\n bottom: 'top-full left-1/2 mt-2 -translate-x-1/2',\r\n left: 'right-full top-1/2 mr-2 -translate-y-1/2',\r\n right: 'left-full top-1/2 ml-2 -translate-y-1/2',\r\n};\r\n\r\n/**\r\n * Dica contextual em hover e foco (WCAG 1.4.13: dispensável com Esc, persistente enquanto hover).\r\n * Não use para informação crítica: ela precisa estar visível na tela.\r\n */\r\nexport const Tooltip = ({ children, content, side = 'top', delay = 150 }: TooltipProps) => {\r\n const [open, setOpen] = useState(false);\r\n const tooltipId = useId();\r\n const timer = useRef<ReturnType<typeof setTimeout>>();\r\n\r\n useEffect(() => () => clearTimeout(timer.current), []);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n const onKey = (e: KeyboardEvent) => e.key === 'Escape' && setOpen(false);\r\n document.addEventListener('keydown', onKey);\r\n return () => document.removeEventListener('keydown', onKey);\r\n }, [open]);\r\n\r\n const show = (withDelay: boolean) => {\r\n clearTimeout(timer.current);\r\n if (withDelay) timer.current = setTimeout(() => setOpen(true), delay);\r\n else setOpen(true);\r\n };\r\n const hide = () => {\r\n clearTimeout(timer.current);\r\n setOpen(false);\r\n };\r\n\r\n const trigger = isValidElement<Record<string, unknown>>(children) ? (\r\n cloneElement(children, { 'aria-describedby': tooltipId })\r\n ) : (\r\n <span aria-describedby={tooltipId} tabIndex={0}>\r\n {children}\r\n </span>\r\n );\r\n\r\n return (\r\n <span\r\n className=\"relative inline-flex\"\r\n onBlur={hide}\r\n onFocus={() => show(false)}\r\n onMouseEnter={() => show(true)}\r\n onMouseLeave={hide}\r\n >\r\n {trigger}\r\n <span\r\n aria-hidden={!open}\r\n className={cn(\r\n 'pointer-events-none absolute z-[var(--sbk-z-tooltip)] w-max max-w-64 rounded-sbk-xs bg-sbk-surface-inverse px-2.5 py-1.5 text-xs font-light text-sbk-fg-inverse shadow-sbk-sm',\r\n 'transition-opacity duration-150 motion-reduce:transition-none',\r\n open ? 'visible opacity-100' : 'invisible opacity-0',\r\n SIDE_CLASS[side],\r\n )}\r\n id={tooltipId}\r\n role=\"tooltip\"\r\n >\r\n {content}\r\n </span>\r\n </span>\r\n );\r\n};\r\n\r\nTooltip.displayName = 'Tooltip';\r\n"],"names":["SIDE_CLASS","Tooltip","children","content","side","delay","open","setOpen","useState","tooltipId","useId","timer","useRef","useEffect","onKey","e","show","withDelay","hide","trigger","isValidElement","cloneElement","jsx","jsxs","cn"],"mappings":";;;AAaA,MAAMA,IAAgE;AAAA,EACpE,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AACT,GAMaC,IAAU,CAAC,EAAE,UAAAC,GAAU,SAAAC,GAAS,MAAAC,IAAO,OAAO,OAAAC,IAAQ,UAAwB;AACzF,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChCC,IAAYC,EAAA,GACZC,IAAQC,EAAA;AAEd,EAAAC,EAAU,MAAM,MAAM,aAAaF,EAAM,OAAO,GAAG,CAAA,CAAE,GAErDE,EAAU,MAAM;AACd,QAAI,CAACP,EAAM;AACX,UAAMQ,IAAQ,CAACC,MAAqBA,EAAE,QAAQ,YAAYR,EAAQ,EAAK;AACvE,oBAAS,iBAAiB,WAAWO,CAAK,GACnC,MAAM,SAAS,oBAAoB,WAAWA,CAAK;AAAA,EAC5D,GAAG,CAACR,CAAI,CAAC;AAET,QAAMU,IAAO,CAACC,MAAuB;AACnC,iBAAaN,EAAM,OAAO,GACtBM,MAAiB,UAAU,WAAW,MAAMV,EAAQ,EAAI,GAAGF,CAAK,MACvD,EAAI;AAAA,EACnB,GACMa,IAAO,MAAM;AACjB,iBAAaP,EAAM,OAAO,GAC1BJ,EAAQ,EAAK;AAAA,EACf,GAEMY,IAAUC,EAAwClB,CAAQ,IAC9DmB,EAAanB,GAAU,EAAE,oBAAoBO,EAAA,CAAW,IAExD,gBAAAa,EAAC,QAAA,EAAK,oBAAkBb,GAAW,UAAU,GAC1C,UAAAP,GACH;AAGF,SACE,gBAAAqB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,QAAQL;AAAA,MACR,SAAS,MAAMF,EAAK,EAAK;AAAA,MACzB,cAAc,MAAMA,EAAK,EAAI;AAAA,MAC7B,cAAcE;AAAA,MAEb,UAAA;AAAA,QAAAC;AAAA,QACD,gBAAAG;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,eAAa,CAAChB;AAAA,YACd,WAAWkB;AAAA,cACT;AAAA,cACA;AAAA,cACAlB,IAAO,wBAAwB;AAAA,cAC/BN,EAAWI,CAAI;AAAA,YAAA;AAAA,YAEjB,IAAIK;AAAA,YACJ,MAAK;AAAA,YAEJ,UAAAN;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAGN;AAEAF,EAAQ,cAAc;"}
@@ -1 +1 @@
1
- {"version":3,"file":"weight.js","sources":["../../../src/components/Typography/weight.ts"],"sourcesContent":["/**\n * Pesos do brand book: 300 (Leve) e 600 (Seminegrito).\n * Os valores legados da 1.x continuam aceitos e são mapeados para o peso oficial mais próximo.\n */\nexport type BrandWeight = 'light' | 'semibold';\n\n/** @deprecated Use 'light' ou 'semibold'. Serão removidos na 3.0. */\nexport type LegacyWeight = 'normal' | 'medium' | 'bold' | 'extrabold';\n\nexport type TextWeight = BrandWeight | LegacyWeight;\n\nexport const weightClass = (weight: TextWeight): string =>\n weight === 'light' || weight === 'normal' ? 'font-light' : 'font-semibold';\n"],"names":["weightClass","weight"],"mappings":"AAWO,MAAMA,IAAc,CAACC,MAC1BA,MAAW,WAAWA,MAAW,WAAW,eAAe;"}
1
+ {"version":3,"file":"weight.js","sources":["../../../src/components/Typography/weight.ts"],"sourcesContent":["/**\r\n * Pesos do brand book: 300 (Leve) e 600 (Seminegrito).\r\n * Os valores legados da 1.x continuam aceitos e são mapeados para o peso oficial mais próximo.\r\n */\r\nexport type BrandWeight = 'light' | 'semibold';\r\n\r\n/** @deprecated Use 'light' ou 'semibold'. Serão removidos na 3.0. */\r\nexport type LegacyWeight = 'normal' | 'medium' | 'bold' | 'extrabold';\r\n\r\nexport type TextWeight = BrandWeight | LegacyWeight;\r\n\r\nexport const weightClass = (weight: TextWeight): string =>\r\n weight === 'light' || weight === 'normal' ? 'font-light' : 'font-semibold';\r\n"],"names":["weightClass","weight"],"mappings":"AAWO,MAAMA,IAAc,CAACC,MAC1BA,MAAW,WAAWA,MAAW,WAAW,eAAe;"}
package/dist/fonts.css CHANGED
@@ -1,8 +1,8 @@
1
- /* ============================================================
2
- @sbkbs/ui · Fonte oficial via Google Fonts (import '@sbkbs/ui/fonts.css')
3
- Somente os pesos do brand book: 300 (Leve) e 600 (Seminegrito).
4
- Para hospedar localmente, prefira @fontsource/plus-jakarta-sans (300 e 600)
5
- e não importe este arquivo.
6
- ============================================================ */
7
-
8
- @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;600&display=swap');
1
+ /* ============================================================
2
+ @sbkbs/ui · Fonte oficial via Google Fonts (import '@sbkbs/ui/fonts.css')
3
+ Somente os pesos do brand book: 300 (Leve) e 600 (Seminegrito).
4
+ Para hospedar localmente, prefira @fontsource/plus-jakarta-sans (300 e 600)
5
+ e não importe este arquivo.
6
+ ============================================================ */
7
+
8
+ @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;600&display=swap');