@sbkbs/ui 1.0.5 → 2.0.0-beta.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 (209) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/MIGRATION.md +96 -0
  3. package/README.md +221 -115
  4. package/dist/assets/favicon/apple-touch-icon.png +0 -0
  5. package/dist/assets/favicon/favicon-96x96.png +0 -0
  6. package/dist/assets/favicon/favicon.ico +0 -0
  7. package/dist/assets/favicon/favicon.svg +1 -0
  8. package/dist/assets/favicon/site.webmanifest +21 -0
  9. package/dist/assets/favicon/web-app-manifest-192x192.png +0 -0
  10. package/dist/assets/favicon/web-app-manifest-512x512.png +0 -0
  11. package/dist/base.css +38 -0
  12. package/dist/components/Accordion/Accordion.d.ts +13 -1
  13. package/dist/components/Accordion/Accordion.js +100 -52
  14. package/dist/components/Accordion/Accordion.js.map +1 -1
  15. package/dist/components/Alert/Alert.d.ts +17 -4
  16. package/dist/components/Alert/Alert.js +64 -20
  17. package/dist/components/Alert/Alert.js.map +1 -1
  18. package/dist/components/Avatar/Avatar.d.ts +17 -0
  19. package/dist/components/Avatar/Avatar.js +66 -0
  20. package/dist/components/Avatar/Avatar.js.map +1 -0
  21. package/dist/components/Badge/Badge.d.ts +11 -2
  22. package/dist/components/Badge/Badge.js +42 -30
  23. package/dist/components/Badge/Badge.js.map +1 -1
  24. package/dist/components/Breadcrumb/Breadcrumb.d.ts +5 -2
  25. package/dist/components/Breadcrumb/Breadcrumb.js +23 -16
  26. package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
  27. package/dist/components/Button/Button.d.ts +10 -8
  28. package/dist/components/Button/Button.js +73 -114
  29. package/dist/components/Button/Button.js.map +1 -1
  30. package/dist/components/Card/Card.d.ts +33 -3
  31. package/dist/components/Card/Card.js +91 -30
  32. package/dist/components/Card/Card.js.map +1 -1
  33. package/dist/components/Checkbox/Checkbox.d.ts +4 -1
  34. package/dist/components/Checkbox/Checkbox.js +32 -31
  35. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  36. package/dist/components/Chip/Chip.d.ts +7 -1
  37. package/dist/components/Chip/Chip.js +19 -9
  38. package/dist/components/Chip/Chip.js.map +1 -1
  39. package/dist/components/Combobox/Combobox.d.ts +10 -2
  40. package/dist/components/Combobox/Combobox.js +146 -133
  41. package/dist/components/Combobox/Combobox.js.map +1 -1
  42. package/dist/components/Divider/Divider.d.ts +7 -1
  43. package/dist/components/Divider/Divider.js +28 -12
  44. package/dist/components/Divider/Divider.js.map +1 -1
  45. package/dist/components/DropdownMenu/DropdownMenu.d.ts +33 -0
  46. package/dist/components/DropdownMenu/DropdownMenu.js +147 -0
  47. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -0
  48. package/dist/components/EmptyState/EmptyState.d.ts +7 -1
  49. package/dist/components/EmptyState/EmptyState.js +28 -19
  50. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  51. package/dist/components/Field/Field.d.ts +21 -0
  52. package/dist/components/Field/Field.js +35 -0
  53. package/dist/components/Field/Field.js.map +1 -0
  54. package/dist/components/FileUpload/FileUpload.d.ts +9 -2
  55. package/dist/components/FileUpload/FileUpload.js +128 -102
  56. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  57. package/dist/components/Footer/Footer.d.ts +19 -6
  58. package/dist/components/Footer/Footer.js +47 -50
  59. package/dist/components/Footer/Footer.js.map +1 -1
  60. package/dist/components/GlassPanel/GlassPanel.d.ts +18 -0
  61. package/dist/components/GlassPanel/GlassPanel.js +39 -0
  62. package/dist/components/GlassPanel/GlassPanel.js.map +1 -0
  63. package/dist/components/Header/Header.d.ts +27 -10
  64. package/dist/components/Header/Header.js +98 -98
  65. package/dist/components/Header/Header.js.map +1 -1
  66. package/dist/components/Highlight/Highlight.d.ts +13 -0
  67. package/dist/components/Highlight/Highlight.js +18 -0
  68. package/dist/components/Highlight/Highlight.js.map +1 -0
  69. package/dist/components/Icon/Icon.d.ts +21 -0
  70. package/dist/components/Icon/Icon.js +31 -0
  71. package/dist/components/Icon/Icon.js.map +1 -0
  72. package/dist/components/IconButton/IconButton.d.ts +12 -0
  73. package/dist/components/IconButton/IconButton.js +49 -0
  74. package/dist/components/IconButton/IconButton.js.map +1 -0
  75. package/dist/components/Input/Input.d.ts +3 -2
  76. package/dist/components/Input/Input.js +51 -69
  77. package/dist/components/Input/Input.js.map +1 -1
  78. package/dist/components/Layout/Layout.d.ts +2 -0
  79. package/dist/components/Layout/Layout.js +24 -18
  80. package/dist/components/Layout/Layout.js.map +1 -1
  81. package/dist/components/Logo/Logo.d.ts +27 -0
  82. package/dist/components/Logo/Logo.js +107 -0
  83. package/dist/components/Logo/Logo.js.map +1 -0
  84. package/dist/components/MiniCard/MiniCard.d.ts +21 -0
  85. package/dist/components/MiniCard/MiniCard.js +90 -0
  86. package/dist/components/MiniCard/MiniCard.js.map +1 -0
  87. package/dist/components/Modal/Modal.d.ts +16 -3
  88. package/dist/components/Modal/Modal.js +124 -93
  89. package/dist/components/Modal/Modal.js.map +1 -1
  90. package/dist/components/Navigation/Navigation.d.ts +1 -0
  91. package/dist/components/Navigation/Navigation.js +14 -14
  92. package/dist/components/Navigation/Navigation.js.map +1 -1
  93. package/dist/components/NumberInput/NumberInput.d.ts +5 -2
  94. package/dist/components/NumberInput/NumberInput.js +98 -128
  95. package/dist/components/NumberInput/NumberInput.js.map +1 -1
  96. package/dist/components/PageHeader/PageHeader.d.ts +8 -1
  97. package/dist/components/PageHeader/PageHeader.js +26 -25
  98. package/dist/components/PageHeader/PageHeader.js.map +1 -1
  99. package/dist/components/Pagination/Pagination.d.ts +15 -2
  100. package/dist/components/Pagination/Pagination.js +68 -34
  101. package/dist/components/Pagination/Pagination.js.map +1 -1
  102. package/dist/components/Paragraph/Paragraph.d.ts +8 -2
  103. package/dist/components/Paragraph/Paragraph.js +39 -36
  104. package/dist/components/Paragraph/Paragraph.js.map +1 -1
  105. package/dist/components/Popover/Popover.d.ts +12 -1
  106. package/dist/components/Popover/Popover.js +49 -37
  107. package/dist/components/Popover/Popover.js.map +1 -1
  108. package/dist/components/ProgressBar/ProgressBar.d.ts +18 -0
  109. package/dist/components/ProgressBar/ProgressBar.js +71 -0
  110. package/dist/components/ProgressBar/ProgressBar.js.map +1 -0
  111. package/dist/components/Radio/Radio.d.ts +2 -1
  112. package/dist/components/Radio/Radio.js +27 -31
  113. package/dist/components/Radio/Radio.js.map +1 -1
  114. package/dist/components/SectionHeader/SectionHeader.d.ts +6 -1
  115. package/dist/components/SectionHeader/SectionHeader.js +14 -12
  116. package/dist/components/SectionHeader/SectionHeader.js.map +1 -1
  117. package/dist/components/Select/Select.d.ts +6 -2
  118. package/dist/components/Select/Select.js +47 -35
  119. package/dist/components/Select/Select.js.map +1 -1
  120. package/dist/components/SideNav/SideNav.d.ts +55 -0
  121. package/dist/components/SideNav/SideNav.js +141 -0
  122. package/dist/components/SideNav/SideNav.js.map +1 -0
  123. package/dist/components/Skeleton/Skeleton.d.ts +12 -1
  124. package/dist/components/Skeleton/Skeleton.js +33 -18
  125. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  126. package/dist/components/Spinner/Spinner.d.ts +15 -0
  127. package/dist/components/Spinner/Spinner.js +57 -0
  128. package/dist/components/Spinner/Spinner.js.map +1 -0
  129. package/dist/components/Stepper/Stepper.d.ts +1 -1
  130. package/dist/components/Stepper/Stepper.js +68 -55
  131. package/dist/components/Stepper/Stepper.js.map +1 -1
  132. package/dist/components/Subtitle/Subtitle.d.ts +9 -3
  133. package/dist/components/Subtitle/Subtitle.js +29 -35
  134. package/dist/components/Subtitle/Subtitle.js.map +1 -1
  135. package/dist/components/Switch/Switch.d.ts +2 -1
  136. package/dist/components/Switch/Switch.js +45 -33
  137. package/dist/components/Switch/Switch.js.map +1 -1
  138. package/dist/components/Table/Table.d.ts +19 -1
  139. package/dist/components/Table/Table.js +48 -11
  140. package/dist/components/Table/Table.js.map +1 -1
  141. package/dist/components/Tabs/Tabs.d.ts +16 -2
  142. package/dist/components/Tabs/Tabs.js +80 -44
  143. package/dist/components/Tabs/Tabs.js.map +1 -1
  144. package/dist/components/Tag/Tag.d.ts +8 -1
  145. package/dist/components/Tag/Tag.js +27 -12
  146. package/dist/components/Tag/Tag.js.map +1 -1
  147. package/dist/components/Textarea/Textarea.d.ts +3 -1
  148. package/dist/components/Textarea/Textarea.js +36 -40
  149. package/dist/components/Textarea/Textarea.js.map +1 -1
  150. package/dist/components/Title/Title.d.ts +9 -3
  151. package/dist/components/Title/Title.js +42 -42
  152. package/dist/components/Title/Title.js.map +1 -1
  153. package/dist/components/Toast/Toast.d.ts +39 -11
  154. package/dist/components/Toast/Toast.js +130 -76
  155. package/dist/components/Toast/Toast.js.map +1 -1
  156. package/dist/components/Tooltip/Tooltip.d.ts +12 -2
  157. package/dist/components/Tooltip/Tooltip.js +50 -32
  158. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  159. package/dist/components/Typography/weight.d.ts +9 -0
  160. package/dist/components/Typography/weight.js +5 -0
  161. package/dist/components/Typography/weight.js.map +1 -0
  162. package/dist/fonts.css +8 -0
  163. package/dist/index.cjs +2 -0
  164. package/dist/index.cjs.map +1 -0
  165. package/dist/index.d.ts +55 -43
  166. package/dist/index.js +118 -83
  167. package/dist/index.js.map +1 -1
  168. package/dist/reset.css +9 -0
  169. package/dist/styles.css +1 -0
  170. package/dist/tailwind.css +153 -0
  171. package/dist/theme/ThemeProvider.d.ts +21 -3
  172. package/dist/theme/ThemeProvider.js +57 -18
  173. package/dist/theme/ThemeProvider.js.map +1 -1
  174. package/dist/theme/tokens.d.ts +43 -0
  175. package/dist/theme/tokens.js +39 -0
  176. package/dist/theme/tokens.js.map +1 -0
  177. package/dist/theme.css +296 -261
  178. package/dist/tokens.css +327 -0
  179. package/dist/utils/cn.d.ts +2 -2
  180. package/dist/utils/cn.js +19 -4
  181. package/dist/utils/cn.js.map +1 -1
  182. package/dist/utils/styles.d.ts +37 -0
  183. package/dist/utils/styles.js +35 -0
  184. package/dist/utils/styles.js.map +1 -0
  185. package/package.json +140 -114
  186. package/dist/components/Accordion/Accordion.stories.d.ts +0 -7
  187. package/dist/components/Alert/Alert.stories.d.ts +0 -8
  188. package/dist/components/Badge/Badge.stories.d.ts +0 -8
  189. package/dist/components/Breadcrumb/Breadcrumb.stories.d.ts +0 -8
  190. package/dist/components/Button/Button.stories.d.ts +0 -7
  191. package/dist/components/Card/Card.stories.d.ts +0 -8
  192. package/dist/components/Checkbox/Checkbox.stories.d.ts +0 -7
  193. package/dist/components/Combobox/Combobox.stories.d.ts +0 -9
  194. package/dist/components/Feedback/Feedback.stories.d.ts +0 -5
  195. package/dist/components/FileUpload/FileUpload.stories.d.ts +0 -10
  196. package/dist/components/Input/Input.stories.d.ts +0 -9
  197. package/dist/components/Modal/Modal.stories.d.ts +0 -8
  198. package/dist/components/NumberInput/NumberInput.stories.d.ts +0 -8
  199. package/dist/components/Pagination/Pagination.stories.d.ts +0 -8
  200. package/dist/components/Radio/Radio.stories.d.ts +0 -7
  201. package/dist/components/Select/Select.stories.d.ts +0 -8
  202. package/dist/components/Stepper/Stepper.stories.d.ts +0 -8
  203. package/dist/components/Switch/Switch.stories.d.ts +0 -8
  204. package/dist/components/Tabs/Tabs.stories.d.ts +0 -8
  205. package/dist/components/Textarea/Textarea.stories.d.ts +0 -7
  206. package/dist/components/Toast/Toast.stories.d.ts +0 -8
  207. package/dist/oficios-ui.css +0 -1
  208. package/dist/oficios-ui.umd.cjs +0 -2
  209. package/dist/oficios-ui.umd.cjs.map +0 -1
@@ -1,110 +1,164 @@
1
- import { jsxs as v, jsx as a } from "react/jsx-runtime";
2
- import { useState as x, useRef as p, useCallback as b, useEffect as w, useMemo as g, useContext as h, createContext as T } from "react";
3
- import { cn as y } from "../../utils/cn.js";
4
- const N = ({
5
- tone: e = "info",
6
- title: o,
7
- description: c,
8
- onDismiss: s,
9
- className: n,
10
- ...i
1
+ import { jsxs as x, jsx as o } from "react/jsx-runtime";
2
+ import { useState as E, useRef as M, useCallback as k, useEffect as z, useMemo as P, useContext as N, createContext as j } from "react";
3
+ import { XCircle as O, AlertTriangle as R, CheckCircle2 as F, Info as S, X as V } from "lucide-react";
4
+ import { cn as b } from "../../utils/cn.js";
5
+ import { focusRing as T, buttonReset as w } from "../../utils/styles.js";
6
+ const X = {
7
+ info: { bar: "bg-sbk-info", icon: "text-sbk-info-fg", Icon: S },
8
+ success: { bar: "bg-sbk-success", icon: "text-sbk-success-fg", Icon: F },
9
+ warning: { bar: "bg-sbk-warning", icon: "text-sbk-warning-fg", Icon: R },
10
+ error: { bar: "bg-sbk-error", icon: "text-sbk-error-fg", Icon: O }
11
+ }, C = ({
12
+ tone: s = "info",
13
+ variant: a = "default",
14
+ title: c,
15
+ description: r,
16
+ action: t,
17
+ onDismiss: i,
18
+ durationMs: l,
19
+ className: u,
20
+ ...d
11
21
  }) => {
12
- const d = {
13
- info: "border-[var(--info-color)]/40",
14
- success: "border-[var(--success-color)]/40",
15
- warning: "border-[var(--warning-color)]/40",
16
- error: "border-[var(--md-error)]/40"
17
- }[e], l = e === "error" || e === "warning" ? "assertive" : "polite", r = e === "error" || e === "warning" ? "alert" : "status";
18
- return /* @__PURE__ */ v(
22
+ const { bar: f, icon: g, Icon: h } = X[s], m = s === "error" || s === "warning";
23
+ return /* @__PURE__ */ x(
19
24
  "div",
20
25
  {
21
- className: y(
22
- "w-[22rem] rounded-[var(--border-radius-md)] border bg-[var(--bg-secondary)] p-3 shadow-[var(--shadow-lg)]",
23
- d,
24
- n
25
- ),
26
26
  "aria-atomic": "true",
27
- "aria-live": l,
28
- onKeyDown: (t) => {
29
- t.key === "Escape" && (s == null || s());
30
- },
31
- role: r,
27
+ "aria-live": m ? "assertive" : "polite",
28
+ className: b(
29
+ "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",
30
+ a === "glass" ? "sbk-glass sbk-glass-strong" : "border border-sbk-line bg-sbk-surface shadow-sbk-md",
31
+ u
32
+ ),
33
+ onKeyDown: (e) => e.key === "Escape" && (i == null ? void 0 : i()),
34
+ role: m ? "alert" : "status",
32
35
  tabIndex: 0,
33
- ...i,
36
+ ...d,
34
37
  children: [
35
- /* @__PURE__ */ v("div", { className: "flex items-start justify-between gap-2", children: [
36
- /* @__PURE__ */ a("p", { className: "m-0 text-sm font-semibold text-[var(--text-primary)]", children: o }),
37
- s && /* @__PURE__ */ a(
38
+ /* @__PURE__ */ o("span", { "aria-hidden": "true", className: b("absolute inset-y-0 left-0 w-1", f) }),
39
+ /* @__PURE__ */ o(h, { "aria-hidden": "true", className: b("mt-0.5 size-5 shrink-0", g), strokeWidth: 1.75 }),
40
+ /* @__PURE__ */ x("div", { className: "grid min-w-0 flex-1 gap-0.5", children: [
41
+ /* @__PURE__ */ o("p", { className: "m-0 text-sm font-semibold text-sbk-fg-heading", children: c }),
42
+ r && /* @__PURE__ */ o("p", { className: "m-0 text-sm font-light text-sbk-fg-muted", children: r }),
43
+ t && /* @__PURE__ */ o(
38
44
  "button",
39
45
  {
40
- "aria-label": "Fechar notificação",
41
- className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--border-radius-sm)] text-[var(--text-secondary)] transition hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--border-color-focus)]",
42
- onClick: s,
46
+ className: b(
47
+ w,
48
+ "mt-1 w-fit cursor-pointer text-sm font-semibold text-sbk-primary underline-offset-4 hover:underline",
49
+ T
50
+ ),
51
+ onClick: t.onClick,
43
52
  type: "button",
44
- children: /* @__PURE__ */ a("span", { "aria-hidden": !0, children: "×" })
53
+ children: t.label
45
54
  }
46
55
  )
47
56
  ] }),
48
- c && /* @__PURE__ */ a("p", { className: "mt-1 text-sm text-[var(--text-secondary)]", children: c })
57
+ i && /* @__PURE__ */ o(
58
+ "button",
59
+ {
60
+ "aria-label": "Fechar notificação",
61
+ className: b(
62
+ w,
63
+ "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",
64
+ T
65
+ ),
66
+ onClick: i,
67
+ type: "button",
68
+ children: /* @__PURE__ */ o(V, { "aria-hidden": "true", className: "size-4" })
69
+ }
70
+ )
49
71
  ]
50
72
  }
51
73
  );
52
- }, f = T(void 0), I = ({ children: e, durationMs: o = 4e3 }) => {
53
- const [c, s] = x([]), n = p(/* @__PURE__ */ new Map()), i = b((r) => {
54
- const t = n.current.get(r);
55
- t && (window.clearTimeout(t), n.current.delete(r)), s((u) => u.filter((m) => m.id !== r));
56
- }, []), d = b(
57
- (r) => {
58
- const t = r.id ?? `toast-${Math.random().toString(36).slice(2, 9)}`;
59
- s((m) => [...m, { ...r, id: t }]);
60
- const u = window.setTimeout(() => i(t), o);
61
- n.current.set(t, u);
74
+ };
75
+ C.displayName = "Toast";
76
+ const v = j(void 0);
77
+ let A = 0;
78
+ const q = ({
79
+ children: s,
80
+ durationMs: a = 5e3,
81
+ max: c = 4,
82
+ position: r = "bottom-right"
83
+ }) => {
84
+ const [t, i] = E([]), l = M(/* @__PURE__ */ new Map()), u = k((e) => {
85
+ clearTimeout(l.current.get(e)), l.current.delete(e), i((n) => n.filter((p) => p.id !== e));
86
+ }, []), d = k(
87
+ (e, n) => {
88
+ n > 0 && l.current.set(
89
+ e,
90
+ setTimeout(() => u(e), n)
91
+ );
62
92
  },
63
- [i, o]
93
+ [u]
94
+ ), f = k(
95
+ (e) => {
96
+ const n = e.id ?? `sbk-toast-${++A}`;
97
+ return i((p) => [...p.filter((I) => I.id !== n), { ...e, id: n }].slice(-c)), d(n, e.durationMs ?? a), n;
98
+ },
99
+ [a, c, d]
64
100
  );
65
- w(() => {
66
- const r = n.current;
101
+ z(() => {
102
+ const e = l.current;
67
103
  return () => {
68
- r.forEach((t) => window.clearTimeout(t)), r.clear();
104
+ e.forEach(clearTimeout), e.clear();
69
105
  };
70
106
  }, []);
71
- const l = g(
72
- () => ({ toasts: c, pushToast: d, dismissToast: i }),
73
- [c, d, i]
107
+ const g = () => {
108
+ l.current.forEach(clearTimeout), l.current.clear();
109
+ }, h = () => t.forEach((e) => d(e.id, e.durationMs ?? a)), m = P(
110
+ () => ({ toasts: t, pushToast: f, dismissToast: u }),
111
+ [t, f, u]
74
112
  );
75
- return /* @__PURE__ */ v(f.Provider, { value: l, children: [
76
- e,
77
- /* @__PURE__ */ a(C, {})
113
+ return /* @__PURE__ */ x(v.Provider, { value: m, children: [
114
+ s,
115
+ /* @__PURE__ */ o(y, { onPause: g, onResume: h, position: r })
78
116
  ] });
79
- }, M = () => {
80
- const e = h(f);
81
- if (!e)
82
- throw new Error("useToast must be used inside ToastProvider");
83
- return e;
84
- }, C = () => {
85
- const e = h(f);
86
- return !e || e.toasts.length === 0 ? null : /* @__PURE__ */ a(
87
- "div",
117
+ }, G = () => {
118
+ const s = N(v);
119
+ if (!s) throw new Error("useToast deve ser usado dentro de ToastProvider");
120
+ return s;
121
+ }, B = {
122
+ "top-right": "top-4 right-4",
123
+ "top-center": "top-4 left-1/2 -translate-x-1/2",
124
+ "bottom-right": "bottom-4 right-4",
125
+ "bottom-center": "bottom-4 left-1/2 -translate-x-1/2",
126
+ "bottom-left": "bottom-4 left-4"
127
+ }, y = ({
128
+ position: s = "bottom-right",
129
+ onPause: a,
130
+ onResume: c
131
+ }) => {
132
+ const r = N(v);
133
+ return !r || r.toasts.length === 0 ? null : /* @__PURE__ */ o(
134
+ "section",
88
135
  {
89
136
  "aria-label": "Notificações",
90
- className: "pointer-events-none fixed bottom-4 right-4 z-[1200] grid gap-2",
91
- role: "region",
92
- children: e.toasts.map((o) => /* @__PURE__ */ a(
93
- N,
137
+ className: b(
138
+ "pointer-events-none fixed z-[var(--sbk-z-toast)] grid gap-2",
139
+ B[s]
140
+ ),
141
+ onBlur: c,
142
+ onFocus: a,
143
+ onMouseEnter: a,
144
+ onMouseLeave: c,
145
+ children: r.toasts.map((t) => /* @__PURE__ */ o(
146
+ C,
94
147
  {
95
- ...o,
148
+ ...t,
96
149
  className: "pointer-events-auto",
97
- onDismiss: () => e.dismissToast(o.id)
150
+ onDismiss: () => r.dismissToast(t.id)
98
151
  },
99
- o.id
152
+ t.id
100
153
  ))
101
154
  }
102
155
  );
103
156
  };
157
+ y.displayName = "ToastViewport";
104
158
  export {
105
- N as Toast,
106
- I as ToastProvider,
107
- C as ToastViewport,
108
- M as useToast
159
+ C as Toast,
160
+ q as ToastProvider,
161
+ y as ToastViewport,
162
+ G as useToast
109
163
  };
110
164
  //# sourceMappingURL=Toast.js.map
@@ -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 { cn } from '../../utils/cn';\n\nexport interface ToastProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n id?: string;\n description?: React.ReactNode;\n onDismiss?: () => void;\n title: React.ReactNode;\n tone?: 'info' | 'success' | 'warning' | 'error';\n}\n\nexport const Toast: React.FC<ToastProps> = ({\n tone = 'info',\n title,\n description,\n onDismiss,\n className,\n ...props\n}) => {\n const toneClass = {\n info: 'border-[var(--info-color)]/40',\n success: 'border-[var(--success-color)]/40',\n warning: 'border-[var(--warning-color)]/40',\n error: 'border-[var(--md-error)]/40',\n }[tone];\n const liveMode = tone === 'error' || tone === 'warning' ? 'assertive' : 'polite';\n const role = tone === 'error' || tone === 'warning' ? 'alert' : 'status';\n\n return (\n <div\n className={cn(\n 'w-[22rem] rounded-[var(--border-radius-md)] border bg-[var(--bg-secondary)] p-3 shadow-[var(--shadow-lg)]',\n toneClass,\n className,\n )}\n aria-atomic=\"true\"\n aria-live={liveMode}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n onDismiss?.();\n }\n }}\n role={role}\n tabIndex={0}\n {...props}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"m-0 text-sm font-semibold text-[var(--text-primary)]\">{title}</p>\n {onDismiss && (\n <button\n aria-label=\"Fechar notificação\"\n className=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--border-radius-sm)] text-[var(--text-secondary)] transition hover:bg-[var(--bg-hover)] hover:text-[var(--text-primary)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--border-color-focus)]\"\n onClick={onDismiss}\n type=\"button\"\n >\n <span aria-hidden>×</span>\n </button>\n )}\n </div>\n {description && <p className=\"mt-1 text-sm text-[var(--text-secondary)]\">{description}</p>}\n </div>\n );\n};\n\ninterface ToastContextValue {\n dismissToast: (id: string) => void;\n pushToast: (toast: Omit<ToastProps, 'id'> & { id?: string }) => void;\n toasts: Array<ToastProps & { id: string }>;\n}\n\nconst ToastContext = createContext<ToastContextValue | undefined>(undefined);\n\nexport interface ToastProviderProps {\n children: React.ReactNode;\n durationMs?: number;\n}\n\nexport const ToastProvider: React.FC<ToastProviderProps> = ({ children, durationMs = 4000 }) => {\n const [toasts, setToasts] = useState<Array<ToastProps & { id: string }>>([]);\n const timeoutIdsRef = useRef<Map<string, number>>(new Map());\n\n const dismissToast = useCallback((id: string) => {\n const timeoutId = timeoutIdsRef.current.get(id);\n if (timeoutId) {\n window.clearTimeout(timeoutId);\n timeoutIdsRef.current.delete(id);\n }\n setToasts((prev) => prev.filter((toast) => toast.id !== id));\n }, []);\n\n const pushToast = useCallback(\n (toast: Omit<ToastProps, 'id'> & { id?: string }) => {\n const id = toast.id ?? `toast-${Math.random().toString(36).slice(2, 9)}`;\n setToasts((prev) => [...prev, { ...toast, id }]);\n const timeoutId = window.setTimeout(() => dismissToast(id), durationMs);\n timeoutIdsRef.current.set(id, timeoutId);\n },\n [dismissToast, durationMs],\n );\n\n useEffect(() => {\n const ids = timeoutIdsRef.current;\n return () => {\n ids.forEach((timeoutId) => window.clearTimeout(timeoutId));\n ids.clear();\n };\n }, []);\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 />\n </ToastContext.Provider>\n );\n};\n\nexport const useToast = (): ToastContextValue => {\n const context = useContext(ToastContext);\n if (!context) {\n throw new Error('useToast must be used inside ToastProvider');\n }\n return context;\n};\n\nexport const ToastViewport: React.FC = () => {\n const context = useContext(ToastContext);\n if (!context || context.toasts.length === 0) {\n return null;\n }\n return (\n <div\n aria-label=\"Notificações\"\n className=\"pointer-events-none fixed bottom-4 right-4 z-[1200] grid gap-2\"\n role=\"region\"\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 </div>\n );\n};\n"],"names":["Toast","tone","title","description","onDismiss","className","props","toneClass","liveMode","role","jsxs","cn","event","jsx","ToastContext","createContext","ToastProvider","children","durationMs","toasts","setToasts","useState","timeoutIdsRef","useRef","dismissToast","useCallback","id","timeoutId","prev","toast","pushToast","useEffect","ids","value","useMemo","ToastViewport","useToast","context","useContext"],"mappings":"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"}
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,7 +1,17 @@
1
1
  import type React from 'react';
2
2
  export interface TooltipProps {
3
+ /** Elemento focável que dispara o tooltip (botão, link). Texto puro recebe tabIndex=0. */
3
4
  children: React.ReactNode;
4
5
  content: React.ReactNode;
5
- side?: 'top' | 'bottom';
6
+ /** Atraso para abrir no hover, em ms. Padrão: 150. */
7
+ delay?: number;
8
+ side?: 'top' | 'bottom' | 'left' | 'right';
6
9
  }
7
- export declare const Tooltip: React.FC<TooltipProps>;
10
+ /**
11
+ * Dica contextual em hover e foco (WCAG 1.4.13: dispensável com Esc, persistente enquanto hover).
12
+ * Não use para informação crítica: ela precisa estar visível na tela.
13
+ */
14
+ export declare const Tooltip: {
15
+ ({ children, content, side, delay }: TooltipProps): import("react/jsx-runtime").JSX.Element;
16
+ displayName: string;
17
+ };
@@ -1,36 +1,54 @@
1
- import { jsx as s, jsxs as d } from "react/jsx-runtime";
2
- import { useState as f, useId as m, isValidElement as u } from "react";
3
- import { cn as x } from "../../utils/cn.js";
4
- const g = ({ children: t, content: r, side: i = "top" }) => {
5
- const [o, e] = f(!1), a = m(), l = i === "top" ? "bottom-full mb-2 left-1/2 -translate-x-1/2" : "top-full mt-2 left-1/2 -translate-x-1/2", n = {
6
- "aria-describedby": a,
7
- onBlur: () => e(!1),
8
- onFocus: () => e(!0),
9
- onKeyDown: (c) => {
10
- c.key === "Escape" && e(!1);
11
- },
12
- onMouseEnter: () => e(!0),
13
- onMouseLeave: () => e(!1)
14
- }, p = u(t) ? /* @__PURE__ */ s("span", { className: "inline-flex", ...n, children: t }) : /* @__PURE__ */ s("span", { className: "inline-flex", tabIndex: 0, ...n, children: t });
15
- return /* @__PURE__ */ d("span", { className: "relative inline-flex", children: [
16
- p,
17
- /* @__PURE__ */ s(
18
- "span",
19
- {
20
- "aria-hidden": !o,
21
- className: x(
22
- "pointer-events-none absolute z-20 whitespace-nowrap rounded bg-[var(--brand-cinza-escuro)] px-2 py-1 text-xs text-white shadow-[var(--shadow-sm)] transition",
23
- o ? "opacity-100" : "opacity-0",
24
- l
25
- ),
26
- id: a,
27
- role: "tooltip",
28
- children: r
29
- }
30
- )
31
- ] });
1
+ import { jsx as l, jsxs as b } from "react/jsx-runtime";
2
+ import { useState as x, useId as y, useRef as v, useEffect as u, isValidElement as k, cloneElement as E } from "react";
3
+ import { cn as g } from "../../utils/cn.js";
4
+ const h = {
5
+ top: "bottom-full left-1/2 mb-2 -translate-x-1/2",
6
+ bottom: "top-full left-1/2 mt-2 -translate-x-1/2",
7
+ left: "right-full top-1/2 mr-2 -translate-y-1/2",
8
+ right: "left-full top-1/2 ml-2 -translate-y-1/2"
9
+ }, w = ({ children: s, content: c, side: m = "top", delay: p = 150 }) => {
10
+ const [e, t] = x(!1), r = y(), o = v();
11
+ u(() => () => clearTimeout(o.current), []), u(() => {
12
+ if (!e) return;
13
+ const n = (f) => f.key === "Escape" && t(!1);
14
+ return document.addEventListener("keydown", n), () => document.removeEventListener("keydown", n);
15
+ }, [e]);
16
+ const i = (n) => {
17
+ clearTimeout(o.current), n ? o.current = setTimeout(() => t(!0), p) : t(!0);
18
+ }, a = () => {
19
+ clearTimeout(o.current), t(!1);
20
+ }, d = k(s) ? E(s, { "aria-describedby": r }) : /* @__PURE__ */ l("span", { "aria-describedby": r, tabIndex: 0, children: s });
21
+ return /* @__PURE__ */ b(
22
+ "span",
23
+ {
24
+ className: "relative inline-flex",
25
+ onBlur: a,
26
+ onFocus: () => i(!1),
27
+ onMouseEnter: () => i(!0),
28
+ onMouseLeave: a,
29
+ children: [
30
+ d,
31
+ /* @__PURE__ */ l(
32
+ "span",
33
+ {
34
+ "aria-hidden": !e,
35
+ className: g(
36
+ "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",
37
+ "transition-opacity duration-150 motion-reduce:transition-none",
38
+ e ? "visible opacity-100" : "invisible opacity-0",
39
+ h[m]
40
+ ),
41
+ id: r,
42
+ role: "tooltip",
43
+ children: c
44
+ }
45
+ )
46
+ ]
47
+ }
48
+ );
32
49
  };
50
+ w.displayName = "Tooltip";
33
51
  export {
34
- g as Tooltip
52
+ w as Tooltip
35
53
  };
36
54
  //# sourceMappingURL=Tooltip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["import type React from 'react';\nimport { isValidElement, useId, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface TooltipProps {\n children: React.ReactNode;\n content: React.ReactNode;\n side?: 'top' | 'bottom';\n}\n\nexport const Tooltip: React.FC<TooltipProps> = ({ children, content, side = 'top' }) => {\n const [open, setOpen] = useState(false);\n const tooltipId = useId();\n const sideClass =\n side === 'top'\n ? 'bottom-full mb-2 left-1/2 -translate-x-1/2'\n : 'top-full mt-2 left-1/2 -translate-x-1/2';\n\n const triggerProps = {\n 'aria-describedby': tooltipId,\n onBlur: () => setOpen(false),\n onFocus: () => setOpen(true),\n onKeyDown: (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n }\n },\n onMouseEnter: () => setOpen(true),\n onMouseLeave: () => setOpen(false),\n };\n\n const trigger = isValidElement(children) ? (\n <span className=\"inline-flex\" {...triggerProps}>\n {children}\n </span>\n ) : (\n <span className=\"inline-flex\" tabIndex={0} {...triggerProps}>\n {children}\n </span>\n );\n\n return (\n <span className=\"relative inline-flex\">\n {trigger}\n <span\n aria-hidden={!open}\n className={cn(\n 'pointer-events-none absolute z-20 whitespace-nowrap rounded bg-[var(--brand-cinza-escuro)] px-2 py-1 text-xs text-white shadow-[var(--shadow-sm)] transition',\n open ? 'opacity-100' : 'opacity-0',\n sideClass,\n )}\n id={tooltipId}\n role=\"tooltip\"\n >\n {content}\n </span>\n </span>\n );\n};\n"],"names":["Tooltip","children","content","side","open","setOpen","useState","tooltipId","useId","sideClass","triggerProps","event","trigger","isValidElement","jsx","jsxs","cn"],"mappings":";;;AAUO,MAAMA,IAAkC,CAAC,EAAE,UAAAC,GAAU,SAAAC,GAAS,MAAAC,IAAO,YAAY;AACtF,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChCC,IAAYC,EAAA,GACZC,IACJN,MAAS,QACL,+CACA,2CAEAO,IAAe;AAAA,IACnB,oBAAoBH;AAAA,IACpB,QAAQ,MAAMF,EAAQ,EAAK;AAAA,IAC3B,SAAS,MAAMA,EAAQ,EAAI;AAAA,IAC3B,WAAW,CAACM,MAA+B;AACzC,MAAIA,EAAM,QAAQ,YAChBN,EAAQ,EAAK;AAAA,IAEjB;AAAA,IACA,cAAc,MAAMA,EAAQ,EAAI;AAAA,IAChC,cAAc,MAAMA,EAAQ,EAAK;AAAA,EAAA,GAG7BO,IAAUC,EAAeZ,CAAQ,sBACpC,QAAA,EAAK,WAAU,eAAe,GAAGS,GAC/B,UAAAT,GACH,IAEA,gBAAAa,EAAC,UAAK,WAAU,eAAc,UAAU,GAAI,GAAGJ,GAC5C,UAAAT,GACH;AAGF,SACE,gBAAAc,EAAC,QAAA,EAAK,WAAU,wBACb,UAAA;AAAA,IAAAH;AAAA,IACD,gBAAAE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,eAAa,CAACV;AAAA,QACd,WAAWY;AAAA,UACT;AAAA,UACAZ,IAAO,gBAAgB;AAAA,UACvBK;AAAA,QAAA;AAAA,QAEF,IAAIF;AAAA,QACJ,MAAK;AAAA,QAEJ,UAAAL;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;"}
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;"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Pesos do brand book: 300 (Leve) e 600 (Seminegrito).
3
+ * Os valores legados da 1.x continuam aceitos e são mapeados para o peso oficial mais próximo.
4
+ */
5
+ export type BrandWeight = 'light' | 'semibold';
6
+ /** @deprecated Use 'light' ou 'semibold'. Serão removidos na 3.0. */
7
+ export type LegacyWeight = 'normal' | 'medium' | 'bold' | 'extrabold';
8
+ export type TextWeight = BrandWeight | LegacyWeight;
9
+ export declare const weightClass: (weight: TextWeight) => string;
@@ -0,0 +1,5 @@
1
+ const t = (o) => o === "light" || o === "normal" ? "font-light" : "font-semibold";
2
+ export {
3
+ t as weightClass
4
+ };
5
+ //# sourceMappingURL=weight.js.map
@@ -0,0 +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;"}
package/dist/fonts.css ADDED
@@ -0,0 +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');