@sbkbs/ui 1.0.6 → 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 (210) 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 +12 -6
  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 -115
  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 +25 -14
  64. package/dist/components/Header/Header.js +88 -148
  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 +12 -6
  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 +11 -3
  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 +41 -53
  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 -263
  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 -117
  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
  210. package/dist/sbk-icon.png +0 -0
@@ -1,113 +1,144 @@
1
- import { jsx as n, jsxs as c } from "react/jsx-runtime";
2
- import { useRef as b, useEffect as y } from "react";
3
- const K = ({
4
- isOpen: t,
1
+ import { jsx as n, jsxs as m } from "react/jsx-runtime";
2
+ import { useRef as p, useId as w, useEffect as L } from "react";
3
+ import { createPortal as q } from "react-dom";
4
+ import { X as K } from "lucide-react";
5
+ import { cn as l } from "../../utils/cn.js";
6
+ import { focusRing as M, transitionColors as P, buttonReset as T } from "../../utils/styles.js";
7
+ const C = {
8
+ sm: "max-w-[25rem]",
9
+ md: "max-w-[32rem]",
10
+ lg: "max-w-[44rem]",
11
+ xl: "max-w-[56rem]",
12
+ full: "max-w-[calc(100vw-2rem)] h-[calc(100dvh-2rem)]"
13
+ }, N = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])', F = ({
14
+ isOpen: d,
5
15
  onClose: o,
6
- title: l,
16
+ title: s,
7
17
  subtitle: i,
8
- children: g,
9
- size: w = "md",
10
- showCloseButton: m = !0,
11
- closeOnOverlayClick: u = !0,
12
- className: p = ""
18
+ children: E,
19
+ footer: f,
20
+ size: j = "md",
21
+ variant: A = "default",
22
+ showCloseButton: u = !0,
23
+ closeOnOverlayClick: S = !0,
24
+ closeOnEscape: b = !0,
25
+ closeLabel: D = "Fechar modal",
26
+ className: I
13
27
  }) => {
14
- const d = b(null), s = b(null);
15
- if (y(() => (t ? (s.current = document.activeElement, document.body.style.overflow = "hidden") : document.body.style.overflow = "", () => {
16
- document.body.style.overflow = "", s.current && s.current.focus();
17
- }), [t]), y(() => {
18
- const r = (e) => {
19
- e.key === "Escape" && t && o();
20
- }, f = (e) => {
21
- if (e.key !== "Tab" || !d.current || !t)
28
+ const a = p(null), h = p(o);
29
+ h.current = o;
30
+ const x = w(), v = w();
31
+ if (L(() => {
32
+ if (!d) return;
33
+ const t = document.activeElement, R = document.body.style.overflow;
34
+ document.body.style.overflow = "hidden";
35
+ const z = requestAnimationFrame(() => {
36
+ var r;
37
+ const e = ((r = a.current) == null ? void 0 : r.querySelector(N)) ?? a.current;
38
+ e == null || e.focus();
39
+ }), g = (e) => {
40
+ if (e.key === "Escape" && b) {
41
+ e.stopPropagation(), h.current();
22
42
  return;
23
- const a = d.current.querySelectorAll(
24
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
25
- );
26
- if (a.length === 0) {
43
+ }
44
+ if (e.key !== "Tab" || !a.current) return;
45
+ const r = Array.from(a.current.querySelectorAll(N));
46
+ if (r.length === 0) {
27
47
  e.preventDefault();
28
48
  return;
29
49
  }
30
- const v = a[0], x = a[a.length - 1], h = document.activeElement;
31
- e.shiftKey && h === v ? (e.preventDefault(), x.focus()) : !e.shiftKey && h === x && (e.preventDefault(), v.focus());
50
+ const k = r[0], y = r[r.length - 1];
51
+ e.shiftKey && document.activeElement === k ? (e.preventDefault(), y.focus()) : !e.shiftKey && document.activeElement === y && (e.preventDefault(), k.focus());
32
52
  };
33
- return t && (document.addEventListener("keydown", r), document.addEventListener("keydown", f), requestAnimationFrame(() => {
34
- var a;
35
- const e = ((a = d.current) == null ? void 0 : a.querySelector(
36
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
37
- )) ?? d.current;
38
- e == null || e.focus();
39
- })), () => {
40
- document.removeEventListener("keydown", r), document.removeEventListener("keydown", f);
53
+ return document.addEventListener("keydown", g), () => {
54
+ var e;
55
+ cancelAnimationFrame(z), document.removeEventListener("keydown", g), document.body.style.overflow = R, (e = t == null ? void 0 : t.focus) == null || e.call(t);
41
56
  };
42
- }, [t, o]), !t)
43
- return null;
44
- const k = (r) => {
45
- u && r.target === r.currentTarget && o();
46
- }, E = (r) => {
47
- u && (r.key === "Enter" || r.key === " ") && r.target === r.currentTarget && o();
48
- }, N = [
49
- "relative z-[var(--z-index-modal)] m-auto flex w-full max-h-[90vh] max-w-full flex-col overflow-hidden rounded-[var(--border-radius-2xl)] border border-[var(--md-outline-variant)] bg-[var(--md-surface)] shadow-[var(--shadow-2xl)]",
50
- {
51
- sm: "max-w-[25rem]",
52
- md: "max-w-[31.25rem]",
53
- lg: "max-w-[43.75rem]",
54
- xl: "max-w-[56.25rem]",
55
- full: "max-h-[90vh] max-w-[90vw]"
56
- }[w],
57
- p
58
- ].filter(Boolean).join(" ");
59
- return /* @__PURE__ */ n(
60
- "div",
61
- {
62
- "aria-labelledby": l ? "modal-title" : void 0,
63
- "aria-modal": "true",
64
- className: "fixed inset-0 z-[var(--z-index-modal-backdrop)] flex min-h-[100dvh] items-center justify-center overflow-y-auto bg-black/50 p-[var(--spacing-lg)] backdrop-blur-[8px]",
65
- onClick: k,
66
- onKeyDown: E,
67
- role: "dialog",
68
- children: /* @__PURE__ */ c("div", { className: N, ref: d, tabIndex: -1, children: [
69
- (l || i || m) && /* @__PURE__ */ c("div", { className: "flex shrink-0 items-start justify-between gap-[var(--spacing-lg)] border-b border-[var(--md-outline-variant)] p-[var(--spacing-2xl)]", children: [
70
- (l || i) && /* @__PURE__ */ c("div", { className: "flex-1", children: [
71
- l && /* @__PURE__ */ n(
72
- "h2",
73
- {
74
- className: "mb-[var(--spacing-xs)] mt-0 text-[var(--font-size-2xl)] font-[var(--font-weight-semibold)] leading-[var(--line-height-tight)] text-[var(--md-on-surface)]",
75
- id: "modal-title",
76
- children: l
77
- }
57
+ }, [d, b]), !d || typeof document > "u") return null;
58
+ const c = A === "glass";
59
+ return q(
60
+ /* @__PURE__ */ n(
61
+ "div",
62
+ {
63
+ className: "fixed inset-0 z-[var(--sbk-z-modal)] flex items-center justify-center overflow-y-auto bg-sbk-overlay p-4 animate-sbk-fade-in",
64
+ "data-testid": "modal-overlay",
65
+ onMouseDown: (t) => {
66
+ S && t.target === t.currentTarget && o();
67
+ },
68
+ children: /* @__PURE__ */ m(
69
+ "div",
70
+ {
71
+ ref: a,
72
+ "aria-describedby": i ? v : void 0,
73
+ "aria-labelledby": s ? x : void 0,
74
+ "aria-modal": "true",
75
+ className: l(
76
+ "relative flex max-h-[calc(100dvh-2rem)] w-full flex-col overflow-hidden rounded-sbk-lg text-sbk-fg outline-none animate-sbk-scale-in motion-reduce:animate-none",
77
+ c ? "sbk-glass sbk-glass-strong" : "border border-sbk-line bg-sbk-surface shadow-sbk-md",
78
+ C[j],
79
+ I
78
80
  ),
79
- i && /* @__PURE__ */ n("p", { className: "m-0 text-[var(--font-size-base)] leading-[var(--line-height-normal)] text-[var(--md-on-surface-variant)]", children: i })
80
- ] }),
81
- m && /* @__PURE__ */ n(
82
- "button",
83
- {
84
- "aria-label": "Fechar modal",
85
- className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--border-radius-md)] border-0 bg-[var(--md-surface-container-high)] text-[var(--md-on-surface)] transition-[var(--transition-all)] hover:bg-[color:color-mix(in_srgb,var(--md-error)_15%,var(--md-surface))] hover:text-[var(--md-error)]",
86
- onClick: o,
87
- type: "button",
88
- children: /* @__PURE__ */ c(
89
- "svg",
81
+ role: "dialog",
82
+ tabIndex: -1,
83
+ children: [
84
+ (s || i || u) && /* @__PURE__ */ m(
85
+ "div",
90
86
  {
91
- fill: "none",
92
- className: "h-5 w-5",
93
- stroke: "currentColor",
94
- strokeWidth: "2",
95
- viewBox: "0 0 24 24",
87
+ className: l(
88
+ "flex shrink-0 items-start justify-between gap-4 px-6 pb-4 pt-6",
89
+ !c && "border-b border-sbk-line"
90
+ ),
96
91
  children: [
97
- /* @__PURE__ */ n("line", { x1: "18", x2: "6", y1: "6", y2: "18" }),
98
- /* @__PURE__ */ n("line", { x1: "6", x2: "18", y1: "6", y2: "18" })
92
+ /* @__PURE__ */ m("div", { className: "grid flex-1 gap-1", children: [
93
+ s && /* @__PURE__ */ n(
94
+ "h2",
95
+ {
96
+ className: "m-0 text-xl font-semibold leading-tight text-sbk-fg-heading",
97
+ id: x,
98
+ children: s
99
+ }
100
+ ),
101
+ i && /* @__PURE__ */ n("p", { className: "m-0 text-sm font-light text-sbk-fg-muted", id: v, children: i })
102
+ ] }),
103
+ u && /* @__PURE__ */ n(
104
+ "button",
105
+ {
106
+ "aria-label": D,
107
+ className: l(
108
+ T,
109
+ "inline-flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-sbk-sm text-sbk-fg-muted hover:bg-sbk-surface-hover hover:text-sbk-fg",
110
+ P,
111
+ M
112
+ ),
113
+ onClick: o,
114
+ type: "button",
115
+ children: /* @__PURE__ */ n(K, { "aria-hidden": "true", className: "size-5" })
116
+ }
117
+ )
99
118
  ]
100
119
  }
120
+ ),
121
+ /* @__PURE__ */ n("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 py-5 font-light", children: E }),
122
+ f && /* @__PURE__ */ n(
123
+ "div",
124
+ {
125
+ className: l(
126
+ "flex shrink-0 items-center justify-end gap-2 px-6 py-4",
127
+ !c && "border-t border-sbk-line bg-sbk-surface-sunken"
128
+ ),
129
+ children: f
130
+ }
101
131
  )
102
- }
103
- )
104
- ] }),
105
- /* @__PURE__ */ n("div", { className: "flex min-h-0 flex-1 flex-col overflow-x-hidden overflow-y-auto p-[var(--spacing-2xl)]", children: g })
106
- ] })
107
- }
132
+ ]
133
+ }
134
+ )
135
+ }
136
+ ),
137
+ document.body
108
138
  );
109
139
  };
140
+ F.displayName = "Modal";
110
141
  export {
111
- K as Modal
142
+ F as Modal
112
143
  };
113
144
  //# sourceMappingURL=Modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useRef } from 'react';\n\nexport interface ModalProps {\n children: React.ReactNode;\n className?: string;\n closeOnOverlayClick?: boolean;\n isOpen: boolean;\n onClose: () => void;\n showCloseButton?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n subtitle?: string;\n title?: string | React.ReactNode;\n}\n\nexport const Modal: React.FC<ModalProps> = ({\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n size = 'md',\n showCloseButton = true,\n closeOnOverlayClick = true,\n className = '',\n}) => {\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const lastFocusedElementRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (isOpen) {\n lastFocusedElementRef.current = document.activeElement as HTMLElement | null;\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n return () => {\n document.body.style.overflow = '';\n if (lastFocusedElementRef.current) {\n lastFocusedElementRef.current.focus();\n }\n };\n }, [isOpen]);\n\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isOpen) {\n onClose();\n }\n };\n const handleTabTrap = (e: KeyboardEvent) => {\n if (e.key !== 'Tab' || !dialogRef.current || !isOpen) {\n return;\n }\n\n const focusable = dialogRef.current.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n\n if (focusable.length === 0) {\n e.preventDefault();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = document.activeElement as HTMLElement | null;\n\n if (e.shiftKey && active === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n };\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n document.addEventListener('keydown', handleTabTrap);\n requestAnimationFrame(() => {\n const initialTarget =\n dialogRef.current?.querySelector<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n ) ?? dialogRef.current;\n initialTarget?.focus();\n });\n }\n return () => {\n document.removeEventListener('keydown', handleEscape);\n document.removeEventListener('keydown', handleTabTrap);\n };\n }, [isOpen, onClose]);\n\n if (!isOpen) {\n return null;\n }\n\n const handleOverlayClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onClose();\n }\n };\n\n const handleOverlayKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (\n closeOnOverlayClick &&\n (e.key === 'Enter' || e.key === ' ') &&\n e.target === e.currentTarget\n ) {\n onClose();\n }\n };\n\n const sizeClassMap: Record<NonNullable<ModalProps['size']>, string> = {\n sm: 'max-w-[25rem]',\n md: 'max-w-[31.25rem]',\n lg: 'max-w-[43.75rem]',\n xl: 'max-w-[56.25rem]',\n full: 'max-h-[90vh] max-w-[90vw]',\n };\n const combinedClass = [\n 'relative z-[var(--z-index-modal)] m-auto flex w-full max-h-[90vh] max-w-full flex-col overflow-hidden rounded-[var(--border-radius-2xl)] border border-[var(--md-outline-variant)] bg-[var(--md-surface)] shadow-[var(--shadow-2xl)]',\n sizeClassMap[size],\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n aria-labelledby={title ? 'modal-title' : undefined}\n aria-modal=\"true\"\n className=\"fixed inset-0 z-[var(--z-index-modal-backdrop)] flex min-h-[100dvh] items-center justify-center overflow-y-auto bg-black/50 p-[var(--spacing-lg)] backdrop-blur-[8px]\"\n onClick={handleOverlayClick}\n onKeyDown={handleOverlayKeyDown}\n role=\"dialog\"\n >\n <div className={combinedClass} ref={dialogRef} tabIndex={-1}>\n {(title || subtitle || showCloseButton) && (\n <div className=\"flex shrink-0 items-start justify-between gap-[var(--spacing-lg)] border-b border-[var(--md-outline-variant)] p-[var(--spacing-2xl)]\">\n {(title || subtitle) && (\n <div className=\"flex-1\">\n {title && (\n <h2\n className=\"mb-[var(--spacing-xs)] mt-0 text-[var(--font-size-2xl)] font-[var(--font-weight-semibold)] leading-[var(--line-height-tight)] text-[var(--md-on-surface)]\"\n id=\"modal-title\"\n >\n {title}\n </h2>\n )}\n {subtitle && (\n <p className=\"m-0 text-[var(--font-size-base)] leading-[var(--line-height-normal)] text-[var(--md-on-surface-variant)]\">\n {subtitle}\n </p>\n )}\n </div>\n )}\n {showCloseButton && (\n <button\n aria-label=\"Fechar modal\"\n className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--border-radius-md)] border-0 bg-[var(--md-surface-container-high)] text-[var(--md-on-surface)] transition-[var(--transition-all)] hover:bg-[color:color-mix(in_srgb,var(--md-error)_15%,var(--md-surface))] hover:text-[var(--md-error)]\"\n onClick={onClose}\n type=\"button\"\n >\n <svg\n fill=\"none\"\n className=\"h-5 w-5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <line x1=\"18\" x2=\"6\" y1=\"6\" y2=\"18\" />\n <line x1=\"6\" x2=\"18\" y1=\"6\" y2=\"18\" />\n </svg>\n </button>\n )}\n </div>\n )}\n <div className=\"flex min-h-0 flex-1 flex-col overflow-x-hidden overflow-y-auto p-[var(--spacing-2xl)]\">\n {children}\n </div>\n </div>\n </div>\n );\n};\n"],"names":["Modal","isOpen","onClose","title","subtitle","children","size","showCloseButton","closeOnOverlayClick","className","dialogRef","useRef","lastFocusedElementRef","useEffect","handleEscape","handleTabTrap","focusable","first","last","active","initialTarget","_a","handleOverlayClick","e","handleOverlayKeyDown","combinedClass","jsx","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Modal.js","sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useId, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { buttonReset, focusRing, transitionColors } from '../../utils/styles';\n\nexport interface ModalProps {\n children: React.ReactNode;\n className?: string;\n closeOnEscape?: boolean;\n closeOnOverlayClick?: boolean;\n /** Rótulo do botão de fechar. Padrão: \"Fechar modal\". */\n closeLabel?: string;\n /** Rodapé fixo (ações). */\n footer?: React.ReactNode;\n isOpen: boolean;\n onClose: () => void;\n showCloseButton?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n subtitle?: React.ReactNode;\n title?: React.ReactNode;\n variant?: 'default' | 'glass';\n}\n\nconst SIZE_CLASS: Record<NonNullable<ModalProps['size']>, string> = {\n sm: 'max-w-[25rem]',\n md: 'max-w-[32rem]',\n lg: 'max-w-[44rem]',\n xl: 'max-w-[56rem]',\n full: 'max-w-[calc(100vw-2rem)] h-[calc(100dvh-2rem)]',\n};\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Diálogo modal com focus trap, restauração de foco, Esc e bloqueio de rolagem.\n * Renderizado em portal no <body>.\n */\nexport const Modal = ({\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n footer,\n size = 'md',\n variant = 'default',\n showCloseButton = true,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n closeLabel = 'Fechar modal',\n className,\n}: ModalProps) => {\n const dialogRef = useRef<HTMLDivElement>(null);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n const titleId = useId();\n const subtitleId = useId();\n\n useEffect(() => {\n if (!isOpen) return;\n const previouslyFocused = document.activeElement as HTMLElement | null;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n const frame = requestAnimationFrame(() => {\n const target = dialogRef.current?.querySelector<HTMLElement>(FOCUSABLE) ?? dialogRef.current;\n target?.focus();\n });\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && closeOnEscape) {\n e.stopPropagation();\n onCloseRef.current();\n return;\n }\n if (e.key !== 'Tab' || !dialogRef.current) return;\n const focusable = Array.from(dialogRef.current.querySelectorAll<HTMLElement>(FOCUSABLE));\n if (focusable.length === 0) {\n e.preventDefault();\n return;\n }\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n cancelAnimationFrame(frame);\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = previousOverflow;\n previouslyFocused?.focus?.();\n };\n }, [isOpen, closeOnEscape]);\n\n if (!isOpen || typeof document === 'undefined') return null;\n\n const isGlass = variant === 'glass';\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-[var(--sbk-z-modal)] flex items-center justify-center overflow-y-auto bg-sbk-overlay p-4 animate-sbk-fade-in\"\n data-testid=\"modal-overlay\"\n onMouseDown={(e) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) onClose();\n }}\n >\n <div\n ref={dialogRef}\n aria-describedby={subtitle ? subtitleId : undefined}\n aria-labelledby={title ? titleId : undefined}\n aria-modal=\"true\"\n className={cn(\n 'relative flex max-h-[calc(100dvh-2rem)] w-full flex-col overflow-hidden rounded-sbk-lg text-sbk-fg outline-none animate-sbk-scale-in motion-reduce:animate-none',\n isGlass\n ? 'sbk-glass sbk-glass-strong'\n : 'border border-sbk-line bg-sbk-surface shadow-sbk-md',\n SIZE_CLASS[size],\n className,\n )}\n role=\"dialog\"\n tabIndex={-1}\n >\n {(title || subtitle || showCloseButton) && (\n <div\n className={cn(\n 'flex shrink-0 items-start justify-between gap-4 px-6 pb-4 pt-6',\n !isGlass && 'border-b border-sbk-line',\n )}\n >\n <div className=\"grid flex-1 gap-1\">\n {title && (\n <h2\n className=\"m-0 text-xl font-semibold leading-tight text-sbk-fg-heading\"\n id={titleId}\n >\n {title}\n </h2>\n )}\n {subtitle && (\n <p className=\"m-0 text-sm font-light text-sbk-fg-muted\" id={subtitleId}>\n {subtitle}\n </p>\n )}\n </div>\n {showCloseButton && (\n <button\n aria-label={closeLabel}\n className={cn(\n buttonReset,\n 'inline-flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-sbk-sm text-sbk-fg-muted hover:bg-sbk-surface-hover hover:text-sbk-fg',\n transitionColors,\n focusRing,\n )}\n onClick={onClose}\n type=\"button\"\n >\n <X aria-hidden=\"true\" className=\"size-5\" />\n </button>\n )}\n </div>\n )}\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-5 font-light\">{children}</div>\n {footer && (\n <div\n className={cn(\n 'flex shrink-0 items-center justify-end gap-2 px-6 py-4',\n !isGlass && 'border-t border-sbk-line bg-sbk-surface-sunken',\n )}\n >\n {footer}\n </div>\n )}\n </div>\n </div>,\n document.body,\n );\n};\n\nModal.displayName = 'Modal';\n"],"names":["SIZE_CLASS","FOCUSABLE","Modal","isOpen","onClose","title","subtitle","children","footer","size","variant","showCloseButton","closeOnOverlayClick","closeOnEscape","closeLabel","className","dialogRef","useRef","onCloseRef","titleId","useId","subtitleId","useEffect","previouslyFocused","previousOverflow","frame","target","_a","handleKeyDown","focusable","first","last","isGlass","createPortal","jsx","e","jsxs","cn","buttonReset","transitionColors","focusRing","X"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import type React from 'react';
2
2
  export interface SidebarProps extends React.HTMLAttributes<HTMLElement> {
3
3
  }
4
+ /** Container lateral simples. Para menu de navegação completo, use SideNav. */
4
5
  export declare const Sidebar: React.FC<SidebarProps>;
5
6
  export interface TopbarProps extends React.HTMLAttributes<HTMLElement> {
6
7
  }
@@ -1,26 +1,26 @@
1
- import { jsx as o } from "react/jsx-runtime";
2
- import { cn as a } from "../../utils/cn.js";
3
- const s = ({ className: r, ...e }) => /* @__PURE__ */ o(
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import { cn as b } from "../../utils/cn.js";
3
+ const a = ({ className: e, ...r }) => /* @__PURE__ */ s(
4
4
  "aside",
5
5
  {
6
- className: a(
7
- "h-full rounded-[var(--border-radius-lg)] border border-[var(--border-color)] bg-[var(--bg-secondary)] p-4",
8
- r
6
+ className: b(
7
+ "h-full rounded-sbk-md border border-sbk-line bg-sbk-surface p-4 text-sbk-fg",
8
+ e
9
9
  ),
10
- ...e
10
+ ...r
11
11
  }
12
- ), c = ({ className: r, ...e }) => /* @__PURE__ */ o(
12
+ ), d = ({ className: e, ...r }) => /* @__PURE__ */ s(
13
13
  "header",
14
14
  {
15
- className: a(
16
- "flex min-h-14 items-center justify-between border-b border-[var(--border-color)] bg-[var(--bg-secondary)] px-4",
17
- r
15
+ className: b(
16
+ "flex min-h-14 items-center justify-between gap-4 border-b border-sbk-line bg-sbk-surface px-4 text-sbk-fg",
17
+ e
18
18
  ),
19
- ...e
19
+ ...r
20
20
  }
21
21
  );
22
22
  export {
23
- s as Sidebar,
24
- c as Topbar
23
+ a as Sidebar,
24
+ d as Topbar
25
25
  };
26
26
  //# sourceMappingURL=Navigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Navigation.js","sources":["../../../src/components/Navigation/Navigation.tsx"],"sourcesContent":["import type React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface SidebarProps extends React.HTMLAttributes<HTMLElement> {}\nexport const Sidebar: React.FC<SidebarProps> = ({ className, ...props }) => (\n <aside\n className={cn(\n 'h-full rounded-[var(--border-radius-lg)] border border-[var(--border-color)] bg-[var(--bg-secondary)] p-4',\n className,\n )}\n {...props}\n />\n);\n\nexport interface TopbarProps extends React.HTMLAttributes<HTMLElement> {}\nexport const Topbar: React.FC<TopbarProps> = ({ className, ...props }) => (\n <header\n className={cn(\n 'flex min-h-14 items-center justify-between border-b border-[var(--border-color)] bg-[var(--bg-secondary)] px-4',\n className,\n )}\n {...props}\n />\n);\n"],"names":["Sidebar","className","props","jsx","cn","Topbar"],"mappings":";;AAIO,MAAMA,IAAkC,CAAC,EAAE,WAAAC,GAAW,GAAGC,QAC9D,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN,GAIWG,IAAgC,CAAC,EAAE,WAAAJ,GAAW,GAAGC,QAC5D,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN;"}
1
+ {"version":3,"file":"Navigation.js","sources":["../../../src/components/Navigation/Navigation.tsx"],"sourcesContent":["import type React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface SidebarProps extends React.HTMLAttributes<HTMLElement> {}\n/** Container lateral simples. Para menu de navegação completo, use SideNav. */\nexport const Sidebar: React.FC<SidebarProps> = ({ className, ...props }) => (\n <aside\n className={cn(\n 'h-full rounded-sbk-md border border-sbk-line bg-sbk-surface p-4 text-sbk-fg',\n className,\n )}\n {...props}\n />\n);\n\nexport interface TopbarProps extends React.HTMLAttributes<HTMLElement> {}\nexport const Topbar: React.FC<TopbarProps> = ({ className, ...props }) => (\n <header\n className={cn(\n 'flex min-h-14 items-center justify-between gap-4 border-b border-sbk-line bg-sbk-surface px-4 text-sbk-fg',\n className,\n )}\n {...props}\n />\n);\n"],"names":["Sidebar","className","props","jsx","cn","Topbar"],"mappings":";;AAKO,MAAMA,IAAkC,CAAC,EAAE,WAAAC,GAAW,GAAGC,QAC9D,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN,GAIWG,IAAgC,CAAC,EAAE,WAAAJ,GAAW,GAAGC,QAC5D,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC;AAAA,MACT;AAAA,MACAH;AAAA,IAAA;AAAA,IAED,GAAGC;AAAA,EAAA;AACN;"}
@@ -1,12 +1,15 @@
1
1
  import React from 'react';
2
- export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'onChange'> {
2
+ export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'onChange' | 'value' | 'defaultValue'> {
3
+ defaultValue?: number;
3
4
  error?: string;
4
5
  helperText?: string;
5
- label?: string;
6
+ label?: React.ReactNode;
6
7
  max?: number;
7
8
  min?: number;
8
9
  onChange?: (value: number | null) => void;
9
10
  size?: 'sm' | 'md' | 'lg';
10
11
  step?: number;
12
+ value?: number | null;
11
13
  }
14
+ /** Campo numérico com botões de incremento. Controlado via `value` + `onChange`. */
12
15
  export declare const NumberInput: React.ForwardRefExoticComponent<NumberInputProps & React.RefAttributes<HTMLInputElement>>;
@@ -1,135 +1,105 @@
1
- import { jsxs as N, jsx as o } from "react/jsx-runtime";
2
- import _ from "react";
3
- import { cn as l } from "../../utils/cn.js";
4
- const M = _.forwardRef(
1
+ import { jsx as r, jsxs as E } from "react/jsx-runtime";
2
+ import R, { useId as T } from "react";
3
+ import { Minus as _, Plus as M } from "lucide-react";
4
+ import { cn as s } from "../../utils/cn.js";
5
+ import { describedBy as P, focusRing as j, transitionColors as F, buttonReset as N } from "../../utils/styles.js";
6
+ import { Field as z } from "../Field/Field.js";
7
+ const A = { sm: "min-h-8 text-sm", md: "min-h-10 text-base", lg: "min-h-12 text-lg" }, B = {
8
+ sm: "w-8 [&_svg]:size-3.5",
9
+ md: "w-10 [&_svg]:size-4",
10
+ lg: "w-12 [&_svg]:size-5"
11
+ }, G = (c, t, o) => Math.min(o ?? Number.POSITIVE_INFINITY, Math.max(t ?? Number.NEGATIVE_INFINITY, c)), H = R.forwardRef(
5
12
  ({
6
- label: x,
7
- error: i,
8
- helperText: v,
9
- size: u = "md",
10
- min: s,
11
- max: n,
12
- step: m = 1,
13
- onChange: r,
14
- className: w,
15
- id: y,
16
- value: b,
17
- defaultValue: a,
18
- disabled: c,
19
- ...g
20
- }, z) => {
21
- const e = y || `number-input-${Math.random().toString(36).slice(2, 9)}`, p = !!i, $ = {
22
- sm: "min-h-8 text-[var(--font-size-sm)]",
23
- md: "min-h-10 text-[var(--font-size-base)]",
24
- lg: "min-h-12 text-[var(--font-size-lg)]"
25
- }, h = {
26
- sm: "h-8 w-7 text-sm",
27
- md: "h-10 w-8 text-base",
28
- lg: "h-12 w-9 text-lg"
29
- }, d = b !== void 0 ? Number(b) : void 0, j = () => {
30
- const t = (d ?? (a !== void 0 ? Number(a) : 0)) - m;
31
- (s === void 0 || t >= s) && (r == null || r(t));
32
- }, k = () => {
33
- const t = (d ?? (a !== void 0 ? Number(a) : 0)) + m;
34
- (n === void 0 || t <= n) && (r == null || r(t));
35
- }, I = (f) => {
36
- const t = f.target.value;
37
- r == null || r(t === "" ? null : Number(t));
38
- };
39
- return /* @__PURE__ */ N("div", { className: "flex flex-col gap-[var(--spacing-xs)]", children: [
40
- x && /* @__PURE__ */ o(
41
- "label",
42
- {
43
- className: "text-[var(--font-size-sm)] font-[var(--font-weight-semibold)] text-[var(--md-on-surface)]",
44
- htmlFor: e,
45
- children: x
46
- }
47
- ),
48
- /* @__PURE__ */ N(
49
- "div",
50
- {
51
- className: l(
52
- "inline-flex overflow-hidden rounded-[var(--border-radius-md)] border border-[var(--md-outline-variant)] bg-[var(--md-surface)] transition focus-within:border-[var(--border-color-focus)] focus-within:[box-shadow:0_0_0_0.1875rem_rgba(47,93,140,0.15)]",
53
- p && "border-[var(--md-error)] focus-within:border-[var(--md-error)]",
54
- c && "cursor-not-allowed opacity-60"
13
+ label: c,
14
+ error: t,
15
+ helperText: o,
16
+ size: m = "md",
17
+ min: n,
18
+ max: a,
19
+ step: p = 1,
20
+ onChange: e,
21
+ className: x,
22
+ id: w,
23
+ value: d,
24
+ defaultValue: f,
25
+ disabled: b,
26
+ required: k,
27
+ ...y
28
+ }, g) => {
29
+ const h = T(), i = w ?? h, u = d ?? f ?? 0, I = (l) => e == null ? void 0 : e(G(u + l * p, n, a)), v = s(
30
+ "flex shrink-0 cursor-pointer items-center justify-center bg-sbk-surface-sunken text-sbk-fg-muted hover:bg-sbk-surface-hover hover:text-sbk-fg disabled:cursor-not-allowed disabled:opacity-50",
31
+ F,
32
+ j,
33
+ B[m]
34
+ );
35
+ return /* @__PURE__ */ r(z, { error: t, helperText: o, id: i, label: c, required: k, children: /* @__PURE__ */ E(
36
+ "div",
37
+ {
38
+ className: s(
39
+ "inline-flex overflow-hidden rounded-sbk-sm border border-sbk-line-strong bg-sbk-surface",
40
+ "focus-within:border-sbk-primary",
41
+ t && "border-sbk-error",
42
+ b && "opacity-60"
43
+ ),
44
+ children: [
45
+ /* @__PURE__ */ r(
46
+ "button",
47
+ {
48
+ "aria-controls": i,
49
+ "aria-label": "Diminuir",
50
+ className: s(N, v, "border-r border-sbk-line"),
51
+ disabled: b || n !== void 0 && u <= n,
52
+ onClick: () => I(-1),
53
+ tabIndex: -1,
54
+ type: "button",
55
+ children: /* @__PURE__ */ r(_, { "aria-hidden": "true" })
56
+ }
55
57
  ),
56
- children: [
57
- /* @__PURE__ */ o(
58
- "button",
59
- {
60
- "aria-label": "Diminuir",
61
- className: l(
62
- "flex shrink-0 items-center justify-center border-r border-[var(--md-outline-variant)] bg-[var(--bg-tertiary)] 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-[var(--border-color-focus)]",
63
- h[u]
64
- ),
65
- disabled: c || s !== void 0 && (d ?? 0) <= s,
66
- onClick: j,
67
- type: "button",
68
- children: "−"
69
- }
70
- ),
71
- /* @__PURE__ */ o(
72
- "input",
73
- {
74
- ref: z,
75
- "aria-describedby": i ? `${e}-error` : v ? `${e}-helper` : void 0,
76
- "aria-invalid": p ? !0 : void 0,
77
- className: l(
78
- "w-full min-w-0 bg-transparent px-3 text-center text-[var(--md-on-surface)] outline-none",
79
- $[u],
80
- w
81
- ),
82
- defaultValue: a,
83
- disabled: c,
84
- id: e,
85
- max: n,
86
- min: s,
87
- step: m,
88
- type: "number",
89
- value: b,
90
- onChange: I,
91
- ...g
92
- }
93
- ),
94
- /* @__PURE__ */ o(
95
- "button",
96
- {
97
- "aria-label": "Aumentar",
98
- className: l(
99
- "flex shrink-0 items-center justify-center border-l border-[var(--md-outline-variant)] bg-[var(--bg-tertiary)] 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-[var(--border-color-focus)]",
100
- h[u]
101
- ),
102
- disabled: c || n !== void 0 && (d ?? 0) >= n,
103
- onClick: k,
104
- type: "button",
105
- children: "+"
106
- }
107
- )
108
- ]
109
- }
110
- ),
111
- i && /* @__PURE__ */ o(
112
- "span",
113
- {
114
- className: "text-[var(--font-size-xs)] text-[var(--md-error)]",
115
- id: `${e}-error`,
116
- role: "alert",
117
- children: i
118
- }
119
- ),
120
- v && !i && /* @__PURE__ */ o(
121
- "span",
122
- {
123
- className: "text-[var(--font-size-xs)] text-[var(--md-on-surface-variant)]",
124
- id: `${e}-helper`,
125
- children: v
126
- }
127
- )
128
- ] });
58
+ /* @__PURE__ */ r(
59
+ "input",
60
+ {
61
+ ref: g,
62
+ "aria-describedby": P(i, t, o),
63
+ "aria-invalid": t ? !0 : void 0,
64
+ className: s(
65
+ "w-full min-w-0 bg-transparent px-3 text-center font-light text-sbk-fg outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none",
66
+ A[m],
67
+ x
68
+ ),
69
+ defaultValue: d === void 0 ? f : void 0,
70
+ disabled: b,
71
+ id: i,
72
+ inputMode: "decimal",
73
+ max: a,
74
+ min: n,
75
+ onChange: (l) => e == null ? void 0 : e(l.target.value === "" ? null : Number(l.target.value)),
76
+ required: k,
77
+ step: p,
78
+ type: "number",
79
+ value: d === void 0 ? void 0 : d ?? "",
80
+ ...y
81
+ }
82
+ ),
83
+ /* @__PURE__ */ r(
84
+ "button",
85
+ {
86
+ "aria-controls": i,
87
+ "aria-label": "Aumentar",
88
+ className: s(N, v, "border-l border-sbk-line"),
89
+ disabled: b || a !== void 0 && u >= a,
90
+ onClick: () => I(1),
91
+ tabIndex: -1,
92
+ type: "button",
93
+ children: /* @__PURE__ */ r(M, { "aria-hidden": "true" })
94
+ }
95
+ )
96
+ ]
97
+ }
98
+ ) });
129
99
  }
130
100
  );
131
- M.displayName = "NumberInput";
101
+ H.displayName = "NumberInput";
132
102
  export {
133
- M as NumberInput
103
+ H as NumberInput
134
104
  };
135
105
  //# sourceMappingURL=NumberInput.js.map