@rendra-ui/web 2.4.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -1
- package/dist/base.css +33 -1
- package/dist/{button-C6rjowQi.js → button-B6-644xP.js} +86 -21
- package/dist/button-B6-644xP.js.map +1 -0
- package/dist/chart.js +63 -15
- package/dist/chart.js.map +1 -1
- package/dist/cli/auditar.js +1 -1
- package/dist/cli/codigos.js +2 -2
- package/dist/cli/executar-auditar.js +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/trocar.js +2 -2
- package/dist/cli/typescript-loader.js +1 -1
- package/dist/{cn-DXDpTGsu.js → cn-TBlI6-gS.js} +2 -2
- package/dist/{cn-DXDpTGsu.js.map → cn-TBlI6-gS.js.map} +1 -1
- package/dist/{components-hp7iWioq.js → components-Btk1cUg2.js} +2 -2
- package/dist/{components-hp7iWioq.js.map → components-Btk1cUg2.js.map} +1 -1
- package/dist/components.css +169 -33
- package/dist/document-viewer.js +6 -6
- package/dist/document-viewer.js.map +1 -1
- package/dist/{empty-state-CdaDLcsB.js → empty-state-DrQjqxvp.js} +36 -12
- package/dist/{empty-state-CdaDLcsB.js.map → empty-state-DrQjqxvp.js.map} +1 -1
- package/dist/features-max-CC6CorTg.js +3 -0
- package/dist/index.js +1075 -339
- package/dist/index.js.map +1 -1
- package/dist/motion-context-BL545cb6.js +222 -0
- package/dist/motion-context-BL545cb6.js.map +1 -0
- package/dist/motion-on-DMoTsWrG.js +29 -0
- package/dist/motion-on-DMoTsWrG.js.map +1 -0
- package/dist/motion.js +3 -0
- package/dist/{rendra-provider-7jUgUHzR.js → rendra-provider-CeCkPafT.js} +9 -5
- package/dist/rendra-provider-CeCkPafT.js.map +1 -0
- package/dist/rich-text-editor.js +4 -4
- package/dist/router-bridge.js +5 -4
- package/dist/router-bridge.js.map +1 -1
- package/dist/tokens.css +63 -15
- package/dist/tooltip-kgsorOg6.js +224 -0
- package/dist/tooltip-kgsorOg6.js.map +1 -0
- package/dist/types/components/rendra-provider.d.ts +12 -1
- package/dist/types/components/rendra-router-bridge.d.ts +4 -1
- package/dist/types/components/ui/accordion.d.ts +1 -1
- package/dist/types/components/ui/badge.d.ts +1 -1
- package/dist/types/components/ui/button.d.ts +1 -1
- package/dist/types/components/ui/dropdown-menu.d.ts +5 -5
- package/dist/types/components/ui/picker-panel.d.ts +1 -1
- package/dist/types/components/ui/popover.d.ts +3 -3
- package/dist/types/components/ui/radio-group.d.ts +1 -1
- package/dist/types/components/ui/skeleton.d.ts +5 -1
- package/dist/types/components/ui/stat-card.d.ts +1 -1
- package/dist/types/components/ui/table.d.ts +0 -6
- package/dist/types/components/ui/tooltip.d.ts +1 -1
- package/dist/types/hooks/use-reduced-motion.d.ts +3 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/lib/motion/count.d.ts +17 -0
- package/dist/types/lib/motion/features-max.d.ts +1 -0
- package/dist/types/lib/motion/index.d.ts +5 -0
- package/dist/types/lib/motion/motion-context.d.ts +58 -0
- package/dist/types/lib/motion/motion-on.d.ts +12 -0
- package/dist/types/lib/motion/native-events.d.ts +16 -0
- package/dist/types/lib/motion/presets.d.ts +92 -0
- package/dist/types/lib/motion/reorder.d.ts +7 -0
- package/dist/types/lib/motion/tokens.d.ts +66 -0
- package/dist/types/lib/motion/use-motion-presets.d.ts +8 -0
- package/dist/types/motion.d.ts +1 -0
- package/dist/{use-breakpoint-Dyp-0E_c.js → use-breakpoint-CNxDwEpc.js} +2 -2
- package/dist/{use-breakpoint-Dyp-0E_c.js.map → use-breakpoint-CNxDwEpc.js.map} +1 -1
- package/dist/use-motion-presets-DCJPBfNJ.js +401 -0
- package/dist/use-motion-presets-DCJPBfNJ.js.map +1 -0
- package/dist/widget-grid.js +3 -3
- package/package.json +10 -1
- package/dist/button-C6rjowQi.js.map +0 -1
- package/dist/rendra-provider-7jUgUHzR.js.map +0 -1
- package/dist/tooltip-bdmbX6vC.js +0 -105
- package/dist/tooltip-bdmbX6vC.js.map +0 -1
package/dist/components.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
1
|
+
/*! Rendra Design System v2.6.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
2
|
|
|
3
3
|
@layer properties {
|
|
4
4
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
--tw-scale-x: 1;
|
|
14
14
|
--tw-scale-y: 1;
|
|
15
15
|
--tw-scale-z: 1;
|
|
16
|
+
--tw-rotate-x: initial;
|
|
17
|
+
--tw-rotate-y: initial;
|
|
18
|
+
--tw-rotate-z: initial;
|
|
19
|
+
--tw-skew-x: initial;
|
|
20
|
+
--tw-skew-y: initial;
|
|
16
21
|
--tw-pan-x: initial;
|
|
17
22
|
--tw-pan-y: initial;
|
|
18
23
|
--tw-pinch-zoom: initial;
|
|
@@ -43,9 +48,6 @@
|
|
|
43
48
|
--tw-ring-offset-color: #fff;
|
|
44
49
|
--tw-ring-offset-shadow: 0 0 #0000;
|
|
45
50
|
--tw-outline-style: solid;
|
|
46
|
-
--tw-duration: initial;
|
|
47
|
-
--tw-ease: initial;
|
|
48
|
-
--tw-content: '';
|
|
49
51
|
--tw-blur: initial;
|
|
50
52
|
--tw-brightness: initial;
|
|
51
53
|
--tw-contrast: initial;
|
|
@@ -59,6 +61,9 @@
|
|
|
59
61
|
--tw-drop-shadow-color: initial;
|
|
60
62
|
--tw-drop-shadow-alpha: 100%;
|
|
61
63
|
--tw-drop-shadow-size: initial;
|
|
64
|
+
--tw-duration: initial;
|
|
65
|
+
--tw-ease: initial;
|
|
66
|
+
--tw-content: '';
|
|
62
67
|
--tw-animation-delay: 0s;
|
|
63
68
|
--tw-animation-direction: normal;
|
|
64
69
|
--tw-animation-duration: initial;
|
|
@@ -99,6 +104,36 @@
|
|
|
99
104
|
.visible {
|
|
100
105
|
visibility: visible;
|
|
101
106
|
}
|
|
107
|
+
.skeleton-shimmer {
|
|
108
|
+
position: relative;
|
|
109
|
+
overflow: hidden;
|
|
110
|
+
&::after {
|
|
111
|
+
content: '';
|
|
112
|
+
position: absolute;
|
|
113
|
+
inset: 0;
|
|
114
|
+
background-image: linear-gradient(
|
|
115
|
+
90deg,
|
|
116
|
+
transparent,
|
|
117
|
+
var(--rendra-muted-foreground),
|
|
118
|
+
transparent
|
|
119
|
+
);
|
|
120
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
121
|
+
background-image: linear-gradient(
|
|
122
|
+
90deg,
|
|
123
|
+
transparent,
|
|
124
|
+
color-mix(in oklab, var(--rendra-muted-foreground) 12%, transparent),
|
|
125
|
+
transparent
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
transform: translateX(-100%);
|
|
129
|
+
animation: rd-shimmer var(--rendra-duration-pulse) var(--rendra-ease-move) infinite;
|
|
130
|
+
}
|
|
131
|
+
@media (prefers-reduced-motion: reduce) {
|
|
132
|
+
&::after {
|
|
133
|
+
animation: none;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
102
137
|
.sr-only {
|
|
103
138
|
position: absolute;
|
|
104
139
|
width: 1px;
|
|
@@ -216,6 +251,12 @@
|
|
|
216
251
|
.left-4 {
|
|
217
252
|
left: 1rem;
|
|
218
253
|
}
|
|
254
|
+
.isolate {
|
|
255
|
+
isolation: isolate;
|
|
256
|
+
}
|
|
257
|
+
.-z-10 {
|
|
258
|
+
z-index: calc(10 * -1);
|
|
259
|
+
}
|
|
219
260
|
.z-10 {
|
|
220
261
|
z-index: 10;
|
|
221
262
|
}
|
|
@@ -766,6 +807,15 @@
|
|
|
766
807
|
transform-origin: 50% 56.604%;
|
|
767
808
|
transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
768
809
|
}
|
|
810
|
+
.origin-\(--radix-dropdown-menu-content-transform-origin\) {
|
|
811
|
+
transform-origin: var(--radix-dropdown-menu-content-transform-origin);
|
|
812
|
+
}
|
|
813
|
+
.origin-\(--radix-popover-content-transform-origin\) {
|
|
814
|
+
transform-origin: var(--radix-popover-content-transform-origin);
|
|
815
|
+
}
|
|
816
|
+
.origin-\(--radix-tooltip-content-transform-origin\) {
|
|
817
|
+
transform-origin: var(--radix-tooltip-content-transform-origin);
|
|
818
|
+
}
|
|
769
819
|
.origin-center {
|
|
770
820
|
transform-origin: center;
|
|
771
821
|
}
|
|
@@ -777,10 +827,10 @@
|
|
|
777
827
|
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
|
|
778
828
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
779
829
|
}
|
|
780
|
-
.scale-
|
|
781
|
-
--tw-scale-x:
|
|
782
|
-
--tw-scale-y:
|
|
783
|
-
--tw-scale-z:
|
|
830
|
+
.scale-90 {
|
|
831
|
+
--tw-scale-x: 90%;
|
|
832
|
+
--tw-scale-y: 90%;
|
|
833
|
+
--tw-scale-z: 90%;
|
|
784
834
|
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
785
835
|
}
|
|
786
836
|
.rotate-90 {
|
|
@@ -793,17 +843,22 @@
|
|
|
793
843
|
transform: translate(-50%, -50%) translate(var(--crop-x, 0px), var(--crop-y, 0px))
|
|
794
844
|
scale(var(--crop-scale, 1));
|
|
795
845
|
}
|
|
846
|
+
.transform {
|
|
847
|
+
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,)
|
|
848
|
+
var(--tw-skew-y,);
|
|
849
|
+
}
|
|
796
850
|
.progress-slide {
|
|
797
|
-
animation: rd-progress-slide
|
|
851
|
+
animation: rd-progress-slide var(--rendra-duration-pulse) linear infinite;
|
|
798
852
|
@media (prefers-reduced-motion: reduce) {
|
|
799
853
|
animation: none;
|
|
800
854
|
}
|
|
801
855
|
}
|
|
802
856
|
.animate-draw {
|
|
803
|
-
animation: rd-draw
|
|
857
|
+
animation: rd-draw var(--rendra-duration-draw) var(--rendra-ease-out)
|
|
858
|
+
var(--rendra-duration-base) both;
|
|
804
859
|
}
|
|
805
860
|
.animate-encaixe {
|
|
806
|
-
animation: rd-encaixe
|
|
861
|
+
animation: rd-encaixe calc(var(--rendra-duration-fast) * 2) var(--rendra-ease-out) both;
|
|
807
862
|
}
|
|
808
863
|
.animate-in {
|
|
809
864
|
animation: enter var(--tw-animation-duration, var(--tw-duration, 0.15s)) var(--tw-ease, ease)
|
|
@@ -811,13 +866,14 @@
|
|
|
811
866
|
var(--tw-animation-direction, normal) var(--tw-animation-fill-mode, none);
|
|
812
867
|
}
|
|
813
868
|
.animate-pop {
|
|
814
|
-
animation: rd-pop
|
|
869
|
+
animation: rd-pop var(--rendra-duration-draw) var(--rendra-ease-spring) both;
|
|
815
870
|
}
|
|
816
871
|
.animate-pulse {
|
|
817
872
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
818
873
|
}
|
|
819
874
|
.animate-shake {
|
|
820
|
-
animation: rd-shake
|
|
875
|
+
animation: rd-shake var(--rendra-duration-draw) var(--rendra-ease-in-out)
|
|
876
|
+
calc(var(--rendra-duration-draw) + var(--rendra-duration-base)) both;
|
|
821
877
|
}
|
|
822
878
|
.animate-spin {
|
|
823
879
|
animation: spin 1s linear infinite;
|
|
@@ -1792,6 +1848,40 @@
|
|
|
1792
1848
|
outline-style: var(--tw-outline-style);
|
|
1793
1849
|
outline-width: 1px;
|
|
1794
1850
|
}
|
|
1851
|
+
.blur {
|
|
1852
|
+
--tw-blur: blur(8px);
|
|
1853
|
+
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,)
|
|
1854
|
+
var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,)
|
|
1855
|
+
var(--tw-drop-shadow,);
|
|
1856
|
+
}
|
|
1857
|
+
.transition {
|
|
1858
|
+
transition-property:
|
|
1859
|
+
color,
|
|
1860
|
+
background-color,
|
|
1861
|
+
border-color,
|
|
1862
|
+
outline-color,
|
|
1863
|
+
text-decoration-color,
|
|
1864
|
+
fill,
|
|
1865
|
+
stroke,
|
|
1866
|
+
--tw-gradient-from,
|
|
1867
|
+
--tw-gradient-via,
|
|
1868
|
+
--tw-gradient-to,
|
|
1869
|
+
opacity,
|
|
1870
|
+
box-shadow,
|
|
1871
|
+
transform,
|
|
1872
|
+
translate,
|
|
1873
|
+
scale,
|
|
1874
|
+
rotate,
|
|
1875
|
+
filter,
|
|
1876
|
+
-webkit-backdrop-filter,
|
|
1877
|
+
backdrop-filter,
|
|
1878
|
+
display,
|
|
1879
|
+
content-visibility,
|
|
1880
|
+
overlay,
|
|
1881
|
+
pointer-events;
|
|
1882
|
+
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1883
|
+
transition-duration: var(--tw-duration, 150ms);
|
|
1884
|
+
}
|
|
1795
1885
|
.transition-\[border-color\,box-shadow\,background-color\] {
|
|
1796
1886
|
transition-property: border-color, box-shadow, background-color;
|
|
1797
1887
|
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
@@ -1812,11 +1902,26 @@
|
|
|
1812
1902
|
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1813
1903
|
transition-duration: var(--tw-duration, 150ms);
|
|
1814
1904
|
}
|
|
1905
|
+
.transition-\[color\,background-color\,border-color\,box-shadow\] {
|
|
1906
|
+
transition-property: color, background-color, border-color, box-shadow;
|
|
1907
|
+
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1908
|
+
transition-duration: var(--tw-duration, 150ms);
|
|
1909
|
+
}
|
|
1815
1910
|
.transition-\[filter\] {
|
|
1816
1911
|
transition-property: filter;
|
|
1817
1912
|
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1818
1913
|
transition-duration: var(--tw-duration, 150ms);
|
|
1819
1914
|
}
|
|
1915
|
+
.transition-\[transform\,opacity\] {
|
|
1916
|
+
transition-property: transform, opacity;
|
|
1917
|
+
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1918
|
+
transition-duration: var(--tw-duration, 150ms);
|
|
1919
|
+
}
|
|
1920
|
+
.transition-\[translate\] {
|
|
1921
|
+
transition-property: translate;
|
|
1922
|
+
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1923
|
+
transition-duration: var(--tw-duration, 150ms);
|
|
1924
|
+
}
|
|
1820
1925
|
.transition-\[width\,box-shadow\] {
|
|
1821
1926
|
transition-property: width, box-shadow;
|
|
1822
1927
|
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
@@ -1827,11 +1932,6 @@
|
|
|
1827
1932
|
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1828
1933
|
transition-duration: var(--tw-duration, 150ms);
|
|
1829
1934
|
}
|
|
1830
|
-
.transition-all {
|
|
1831
|
-
transition-property: all;
|
|
1832
|
-
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1833
|
-
transition-duration: var(--tw-duration, 150ms);
|
|
1834
|
-
}
|
|
1835
1935
|
.transition-colors {
|
|
1836
1936
|
transition-property:
|
|
1837
1937
|
color, background-color, border-color, outline-color, text-decoration-color, fill, stroke,
|
|
@@ -1849,6 +1949,18 @@
|
|
|
1849
1949
|
transition-timing-function: var(--tw-ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1850
1950
|
transition-duration: var(--tw-duration, 150ms);
|
|
1851
1951
|
}
|
|
1952
|
+
.duration-\(--rendra-duration-base\) {
|
|
1953
|
+
--tw-duration: var(--rendra-duration-base);
|
|
1954
|
+
transition-duration: var(--rendra-duration-base);
|
|
1955
|
+
}
|
|
1956
|
+
.duration-\(--rendra-duration-fast\) {
|
|
1957
|
+
--tw-duration: var(--rendra-duration-fast);
|
|
1958
|
+
transition-duration: var(--rendra-duration-fast);
|
|
1959
|
+
}
|
|
1960
|
+
.duration-\(--rendra-duration-press\) {
|
|
1961
|
+
--tw-duration: var(--rendra-duration-press);
|
|
1962
|
+
transition-duration: var(--rendra-duration-press);
|
|
1963
|
+
}
|
|
1852
1964
|
.duration-150 {
|
|
1853
1965
|
--tw-duration: 150ms;
|
|
1854
1966
|
transition-duration: 150ms;
|
|
@@ -1857,17 +1969,17 @@
|
|
|
1857
1969
|
--tw-duration: 200ms;
|
|
1858
1970
|
transition-duration: 200ms;
|
|
1859
1971
|
}
|
|
1860
|
-
.
|
|
1861
|
-
--tw-
|
|
1862
|
-
transition-
|
|
1972
|
+
.ease-linear {
|
|
1973
|
+
--tw-ease: linear;
|
|
1974
|
+
transition-timing-function: linear;
|
|
1863
1975
|
}
|
|
1864
|
-
.
|
|
1865
|
-
--tw-
|
|
1866
|
-
transition-
|
|
1976
|
+
.ease-move {
|
|
1977
|
+
--tw-ease: var(--rendra-ease-move);
|
|
1978
|
+
transition-timing-function: var(--rendra-ease-move);
|
|
1867
1979
|
}
|
|
1868
1980
|
.ease-out {
|
|
1869
|
-
--tw-ease:
|
|
1870
|
-
transition-timing-function:
|
|
1981
|
+
--tw-ease: var(--rendra-ease-out);
|
|
1982
|
+
transition-timing-function: var(--rendra-ease-out);
|
|
1871
1983
|
}
|
|
1872
1984
|
.fade-in-0 {
|
|
1873
1985
|
--tw-enter-opacity: calc(0/100);
|
|
@@ -1881,6 +1993,10 @@
|
|
|
1881
1993
|
-webkit-user-select: none;
|
|
1882
1994
|
user-select: none;
|
|
1883
1995
|
}
|
|
1996
|
+
.tabs-clip {
|
|
1997
|
+
clip-path: inset(0 var(--tabs-r, 100%) 0 var(--tabs-l, 0px));
|
|
1998
|
+
transition: clip-path var(--rendra-duration-move) var(--rendra-ease-move);
|
|
1999
|
+
}
|
|
1884
2000
|
.zoom-in-95 {
|
|
1885
2001
|
--tw-enter-scale: calc(95 * 1%);
|
|
1886
2002
|
--tw-enter-scale: 0.95;
|
|
@@ -1930,6 +2046,9 @@
|
|
|
1930
2046
|
) {
|
|
1931
2047
|
color: var(--rendra-primary-foreground);
|
|
1932
2048
|
}
|
|
2049
|
+
.group-data-\[state\=checked\]\:opacity-100:is(:where(.group)[data-state='checked'] *) {
|
|
2050
|
+
opacity: 100%;
|
|
2051
|
+
}
|
|
1933
2052
|
.group-data-\[state\=open\]\:hidden:is(:where(.group)[data-state='open'] *) {
|
|
1934
2053
|
display: none;
|
|
1935
2054
|
}
|
|
@@ -2229,10 +2348,16 @@
|
|
|
2229
2348
|
--tw-scale-z: 95%;
|
|
2230
2349
|
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
2231
2350
|
}
|
|
2232
|
-
.active\:scale-
|
|
2233
|
-
--tw-scale-x:
|
|
2234
|
-
--tw-scale-y:
|
|
2235
|
-
--tw-scale-z:
|
|
2351
|
+
.active\:scale-97:active {
|
|
2352
|
+
--tw-scale-x: 97%;
|
|
2353
|
+
--tw-scale-y: 97%;
|
|
2354
|
+
--tw-scale-z: 97%;
|
|
2355
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
2356
|
+
}
|
|
2357
|
+
.active\:scale-100:active {
|
|
2358
|
+
--tw-scale-x: 100%;
|
|
2359
|
+
--tw-scale-y: 100%;
|
|
2360
|
+
--tw-scale-z: 100%;
|
|
2236
2361
|
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
2237
2362
|
}
|
|
2238
2363
|
.active\:cursor-grabbing:active {
|
|
@@ -2437,9 +2562,13 @@
|
|
|
2437
2562
|
.data-\[state\=checked\]\:ring-primary[data-state='checked'] {
|
|
2438
2563
|
--tw-ring-color: var(--rendra-primary);
|
|
2439
2564
|
}
|
|
2440
|
-
.data-\[state\=checked\]\:
|
|
2441
|
-
--tw-
|
|
2442
|
-
--
|
|
2565
|
+
.data-\[state\=checked\]\:duration-\(--rendra-duration-fast\)[data-state='checked'] {
|
|
2566
|
+
--tw-duration: var(--rendra-duration-fast);
|
|
2567
|
+
transition-duration: var(--rendra-duration-fast);
|
|
2568
|
+
}
|
|
2569
|
+
.data-\[state\=checked\]\:zoom-in-90[data-state='checked'] {
|
|
2570
|
+
--tw-enter-scale: calc(90 * 1%);
|
|
2571
|
+
--tw-enter-scale: 0.9;
|
|
2443
2572
|
}
|
|
2444
2573
|
.data-\[state\=closed\]\:animate-accordion-up[data-state='closed'] {
|
|
2445
2574
|
animation: accordion-up var(--tw-animation-duration, var(--tw-duration, 0.2s))
|
|
@@ -2456,6 +2585,10 @@
|
|
|
2456
2585
|
var(--tw-animation-delay, 0s) var(--tw-animation-iteration-count, 1)
|
|
2457
2586
|
var(--tw-animation-direction, normal) var(--tw-animation-fill-mode, none);
|
|
2458
2587
|
}
|
|
2588
|
+
.data-\[state\=closed\]\:duration-\(--rendra-duration-fast\)[data-state='closed'] {
|
|
2589
|
+
--tw-duration: var(--rendra-duration-fast);
|
|
2590
|
+
transition-duration: var(--rendra-duration-fast);
|
|
2591
|
+
}
|
|
2459
2592
|
.data-\[state\=closed\]\:fade-out-0[data-state='closed'] {
|
|
2460
2593
|
--tw-exit-opacity: calc(0/100);
|
|
2461
2594
|
--tw-exit-opacity: 0;
|
|
@@ -2482,6 +2615,9 @@
|
|
|
2482
2615
|
.data-\[state\=indeterminate\]\:text-primary-foreground[data-state='indeterminate'] {
|
|
2483
2616
|
color: var(--rendra-primary-foreground);
|
|
2484
2617
|
}
|
|
2618
|
+
.data-\[state\=instant-open\]\:animate-none[data-state='instant-open'] {
|
|
2619
|
+
animation: none;
|
|
2620
|
+
}
|
|
2485
2621
|
.data-\[state\=open\]\:animate-accordion-down[data-state='open'] {
|
|
2486
2622
|
animation: accordion-down var(--tw-animation-duration, var(--tw-duration, 0.2s))
|
|
2487
2623
|
var(--tw-ease, ease-out) var(--tw-animation-delay, 0s) var(--tw-animation-iteration-count, 1)
|
package/dist/document-viewer.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as cn } from "./cn-
|
|
3
|
-
import { t as Button } from "./button-
|
|
4
|
-
import { t as EmptyState } from "./empty-state-
|
|
1
|
+
/*! Rendra Design System v2.6.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-TBlI6-gS.js";
|
|
3
|
+
import { t as Button } from "./button-B6-644xP.js";
|
|
4
|
+
import { t as EmptyState } from "./empty-state-DrQjqxvp.js";
|
|
5
5
|
import { ChevronLeft, ChevronRight, ExternalLink, ZoomIn, ZoomOut } from "lucide-react";
|
|
6
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
6
|
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/ui/document-viewer.tsx
|
|
9
9
|
var MIN_SCALE = .25;
|
|
10
10
|
var MAX_SCALE = 3;
|
|
@@ -129,7 +129,7 @@ function DocumentViewer({ url, title, className, emptyTitle = "Nenhum documento
|
|
|
129
129
|
})
|
|
130
130
|
})
|
|
131
131
|
}),
|
|
132
|
-
status === "ready" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
132
|
+
status === "ready" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
133
133
|
className: "flex shrink-0 items-center justify-between gap-3 border-b bg-card px-3 py-2",
|
|
134
134
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
135
135
|
className: "flex items-center gap-1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-viewer.js","names":[],"sources":["../src/components/ui/document-viewer.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight, ExternalLink, ZoomIn, ZoomOut } from 'lucide-react'\nimport { useEffect, useRef, useState } from 'react'\nimport { Button } from '@/components/ui/button'\nimport { EmptyState } from '@/components/ui/empty-state'\nimport { cn } from '@/lib/cn'\n\n/*\n * Visualizador de documentos PDF. Carrega o pdfjs-dist sob demanda (import dinâmico), com o\n * worker também sob demanda, para o pacote principal nunca pagar o custo de quem não usa o\n * visualizador. url null é o estado vazio legítimo (nenhum documento escolhido ainda). Falha\n * (CORS, arquivo inválido) é declarada, nunca uma tela em branco: sempre com o link \"Abrir em\n * nova aba\".\n */\n\n// pdfjs-dist é grande e só entra no bundle de quem realmente usa o DocumentViewer: os tipos\n// abaixo são só de compilação (import de tipo), o import de valor é sempre dinâmico (import()).\ntype PdfDocumentProxy = import('pdfjs-dist').PDFDocumentProxy\n// destroy() vive na tarefa de carregamento (o que getDocument devolve antes do .promise),\n// não no documento já resolvido: é ela que precisa ser guardada para liberar depois.\ntype PdfLoadingTask = import('pdfjs-dist').PDFDocumentLoadingTask\n\ntype Status = 'empty' | 'loading' | 'ready' | 'error'\n\nexport interface DocumentViewerProps {\n /** Endereço do PDF. null é o estado vazio legítimo (nenhum documento escolhido ainda). */\n url: string | null\n /** Nome acessível do documento (aria-label do visualizador). */\n title: string\n className?: string\n emptyTitle?: string\n emptyDescription?: string\n loadingLabel?: string\n errorTitle?: string\n errorDescription?: string\n openInNewTabLabel?: string\n zoomInLabel?: string\n zoomOutLabel?: string\n previousPageLabel?: string\n nextPageLabel?: string\n}\n\nconst MIN_SCALE = 0.25\nconst MAX_SCALE = 3\nconst ZOOM_STEP = 1.25\n\n/** Um visualizador de documento por tela; nunca crie um segundo para PDF. */\nexport function DocumentViewer({\n url,\n title,\n className,\n emptyTitle = 'Nenhum documento selecionado',\n emptyDescription = 'Escolha um arquivo PDF para visualizar aqui.',\n loadingLabel = 'Carregando documento...',\n errorTitle = 'Não foi possível abrir o documento',\n errorDescription = 'O arquivo pode estar indisponível, corrompido ou bloqueado por CORS.',\n openInNewTabLabel = 'Abrir em nova aba',\n zoomInLabel = 'Aumentar zoom',\n zoomOutLabel = 'Diminuir zoom',\n previousPageLabel = 'Página anterior',\n nextPageLabel = 'Próxima página',\n}: DocumentViewerProps) {\n const [status, setStatus] = useState<Status>(url ? 'loading' : 'empty')\n const [page, setPage] = useState(1)\n const [numPages, setNumPages] = useState(0)\n const [scale, setScale] = useState(1)\n const [fitToWidth, setFitToWidth] = useState(true)\n const pdfRef = useRef<PdfDocumentProxy | null>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n // Carrega o documento (ou reinicia o estado vazio) sempre que a url muda. Libera a tarefa\n // de carregamento (destroy) ao trocar de url e ao desmontar, para não vazar memória nem o\n // worker que o pdfjs sobe para cada documento.\n useEffect(() => {\n let cancelled = false\n let loadingTask: PdfLoadingTask | null = null\n pdfRef.current = null\n setPage(1)\n setNumPages(0)\n setFitToWidth(true)\n setScale(1)\n\n if (!url) {\n setStatus('empty')\n return\n }\n const targetUrl: string = url\n\n setStatus('loading')\n async function load() {\n try {\n const [pdfjsLib, workerModule] = await Promise.all([\n import('pdfjs-dist'),\n import('pdfjs-dist/build/pdf.worker.min.mjs?url'),\n ])\n pdfjsLib.GlobalWorkerOptions.workerSrc = workerModule.default\n if (cancelled) return\n loadingTask = pdfjsLib.getDocument({ url: targetUrl })\n const doc = await loadingTask.promise\n if (cancelled) return\n pdfRef.current = doc\n setNumPages(doc.numPages)\n setStatus('ready')\n } catch {\n if (cancelled) return\n setStatus('error')\n }\n }\n void load()\n return () => {\n cancelled = true\n void loadingTask?.destroy()\n }\n }, [url])\n\n // Desenha a página atual sempre que ela, o zoom ou o modo \"ajustar à largura\" mudam.\n useEffect(() => {\n if (status !== 'ready' || !pdfRef.current) return\n let cancelled = false\n async function draw() {\n const doc = pdfRef.current\n if (!doc) return\n const pdfPage = await doc.getPage(page)\n if (cancelled) return\n const natural = pdfPage.getViewport({ scale: 1 })\n const containerWidth = containerRef.current?.clientWidth ?? 0\n const effectiveScale =\n fitToWidth && containerWidth > 0 ? containerWidth / natural.width : scale\n const viewport = pdfPage.getViewport({ scale: effectiveScale })\n const canvas = canvasRef.current\n if (!canvas) return\n canvas.width = viewport.width\n canvas.height = viewport.height\n const ctx = canvas.getContext('2d')\n // Sem contexto 2D disponível (ambiente sem canvas real): mantém os controles\n // funcionando, só não desenha o pixel a pixel.\n if (!ctx) return\n await pdfPage.render({ canvas, canvasContext: ctx, viewport }).promise\n }\n void draw()\n return () => {\n cancelled = true\n }\n }, [status, page, scale, fitToWidth])\n\n const zoomIn = () => {\n setFitToWidth(false)\n setScale((s) => Math.min(MAX_SCALE, s * ZOOM_STEP))\n }\n const zoomOut = () => {\n setFitToWidth(false)\n setScale((s) => Math.max(MIN_SCALE, s / ZOOM_STEP))\n }\n\n return (\n <div\n data-rendra=\"DOC-001\"\n role=\"group\"\n aria-label={title}\n className={cn(\n 'flex h-viewer min-h-0 flex-col overflow-hidden rounded-surface border bg-card',\n className,\n )}\n >\n {status === 'empty' && (\n <EmptyState title={emptyTitle} description={emptyDescription} className=\"m-auto\" />\n )}\n\n {status === 'loading' && (\n <div\n className=\"m-auto flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground\"\n role=\"status\"\n >\n {loadingLabel}\n </div>\n )}\n\n {status === 'error' && (\n <EmptyState\n type=\"error\"\n title={errorTitle}\n description={errorDescription}\n className=\"m-auto\"\n actions={\n url && (\n <Button variant=\"outline\" asChild>\n <a href={url} target=\"_blank\" rel=\"noreferrer\">\n <ExternalLink aria-hidden />\n {openInNewTabLabel}\n </a>\n </Button>\n )\n }\n />\n )}\n\n {status === 'ready' && (\n <>\n <div className=\"flex shrink-0 items-center justify-between gap-3 border-b bg-card px-3 py-2\">\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={zoomOutLabel}\n icon={<ZoomOut />}\n onClick={zoomOut}\n />\n <span className=\"w-12 text-center text-xs text-muted-foreground tabular-nums\">\n {fitToWidth ? 'Ajustar' : `${Math.round(scale * 100)}%`}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={zoomInLabel}\n icon={<ZoomIn />}\n onClick={zoomIn}\n />\n </div>\n {numPages > 1 && (\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={previousPageLabel}\n icon={<ChevronLeft />}\n disabled={page <= 1}\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n />\n <span className=\"text-xs text-muted-foreground tabular-nums\" aria-live=\"polite\">\n {page} de {numPages}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={nextPageLabel}\n icon={<ChevronRight />}\n disabled={page >= numPages}\n onClick={() => setPage((p) => Math.min(numPages, p + 1))}\n />\n </div>\n )}\n </div>\n <div\n ref={containerRef}\n className=\"flex min-h-0 flex-1 items-center justify-center overflow-auto bg-muted p-4\"\n >\n <canvas ref={canvasRef} className=\"max-w-full rounded-item bg-card shadow-sm\" />\n </div>\n </>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"document-viewer.js","names":[],"sources":["../src/components/ui/document-viewer.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight, ExternalLink, ZoomIn, ZoomOut } from 'lucide-react'\nimport { useEffect, useRef, useState } from 'react'\nimport { Button } from '@/components/ui/button'\nimport { EmptyState } from '@/components/ui/empty-state'\nimport { cn } from '@/lib/cn'\n\n/*\n * Visualizador de documentos PDF. Carrega o pdfjs-dist sob demanda (import dinâmico), com o\n * worker também sob demanda, para o pacote principal nunca pagar o custo de quem não usa o\n * visualizador. url null é o estado vazio legítimo (nenhum documento escolhido ainda). Falha\n * (CORS, arquivo inválido) é declarada, nunca uma tela em branco: sempre com o link \"Abrir em\n * nova aba\".\n */\n\n// pdfjs-dist é grande e só entra no bundle de quem realmente usa o DocumentViewer: os tipos\n// abaixo são só de compilação (import de tipo), o import de valor é sempre dinâmico (import()).\ntype PdfDocumentProxy = import('pdfjs-dist').PDFDocumentProxy\n// destroy() vive na tarefa de carregamento (o que getDocument devolve antes do .promise),\n// não no documento já resolvido: é ela que precisa ser guardada para liberar depois.\ntype PdfLoadingTask = import('pdfjs-dist').PDFDocumentLoadingTask\n\ntype Status = 'empty' | 'loading' | 'ready' | 'error'\n\nexport interface DocumentViewerProps {\n /** Endereço do PDF. null é o estado vazio legítimo (nenhum documento escolhido ainda). */\n url: string | null\n /** Nome acessível do documento (aria-label do visualizador). */\n title: string\n className?: string\n emptyTitle?: string\n emptyDescription?: string\n loadingLabel?: string\n errorTitle?: string\n errorDescription?: string\n openInNewTabLabel?: string\n zoomInLabel?: string\n zoomOutLabel?: string\n previousPageLabel?: string\n nextPageLabel?: string\n}\n\nconst MIN_SCALE = 0.25\nconst MAX_SCALE = 3\nconst ZOOM_STEP = 1.25\n\n/** Um visualizador de documento por tela; nunca crie um segundo para PDF. */\nexport function DocumentViewer({\n url,\n title,\n className,\n emptyTitle = 'Nenhum documento selecionado',\n emptyDescription = 'Escolha um arquivo PDF para visualizar aqui.',\n loadingLabel = 'Carregando documento...',\n errorTitle = 'Não foi possível abrir o documento',\n errorDescription = 'O arquivo pode estar indisponível, corrompido ou bloqueado por CORS.',\n openInNewTabLabel = 'Abrir em nova aba',\n zoomInLabel = 'Aumentar zoom',\n zoomOutLabel = 'Diminuir zoom',\n previousPageLabel = 'Página anterior',\n nextPageLabel = 'Próxima página',\n}: DocumentViewerProps) {\n const [status, setStatus] = useState<Status>(url ? 'loading' : 'empty')\n const [page, setPage] = useState(1)\n const [numPages, setNumPages] = useState(0)\n const [scale, setScale] = useState(1)\n const [fitToWidth, setFitToWidth] = useState(true)\n const pdfRef = useRef<PdfDocumentProxy | null>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n\n // Carrega o documento (ou reinicia o estado vazio) sempre que a url muda. Libera a tarefa\n // de carregamento (destroy) ao trocar de url e ao desmontar, para não vazar memória nem o\n // worker que o pdfjs sobe para cada documento.\n useEffect(() => {\n let cancelled = false\n let loadingTask: PdfLoadingTask | null = null\n pdfRef.current = null\n setPage(1)\n setNumPages(0)\n setFitToWidth(true)\n setScale(1)\n\n if (!url) {\n setStatus('empty')\n return\n }\n const targetUrl: string = url\n\n setStatus('loading')\n async function load() {\n try {\n const [pdfjsLib, workerModule] = await Promise.all([\n import('pdfjs-dist'),\n import('pdfjs-dist/build/pdf.worker.min.mjs?url'),\n ])\n pdfjsLib.GlobalWorkerOptions.workerSrc = workerModule.default\n if (cancelled) return\n loadingTask = pdfjsLib.getDocument({ url: targetUrl })\n const doc = await loadingTask.promise\n if (cancelled) return\n pdfRef.current = doc\n setNumPages(doc.numPages)\n setStatus('ready')\n } catch {\n if (cancelled) return\n setStatus('error')\n }\n }\n void load()\n return () => {\n cancelled = true\n void loadingTask?.destroy()\n }\n }, [url])\n\n // Desenha a página atual sempre que ela, o zoom ou o modo \"ajustar à largura\" mudam.\n useEffect(() => {\n if (status !== 'ready' || !pdfRef.current) return\n let cancelled = false\n async function draw() {\n const doc = pdfRef.current\n if (!doc) return\n const pdfPage = await doc.getPage(page)\n if (cancelled) return\n const natural = pdfPage.getViewport({ scale: 1 })\n const containerWidth = containerRef.current?.clientWidth ?? 0\n const effectiveScale =\n fitToWidth && containerWidth > 0 ? containerWidth / natural.width : scale\n const viewport = pdfPage.getViewport({ scale: effectiveScale })\n const canvas = canvasRef.current\n if (!canvas) return\n canvas.width = viewport.width\n canvas.height = viewport.height\n const ctx = canvas.getContext('2d')\n // Sem contexto 2D disponível (ambiente sem canvas real): mantém os controles\n // funcionando, só não desenha o pixel a pixel.\n if (!ctx) return\n await pdfPage.render({ canvas, canvasContext: ctx, viewport }).promise\n }\n void draw()\n return () => {\n cancelled = true\n }\n }, [status, page, scale, fitToWidth])\n\n const zoomIn = () => {\n setFitToWidth(false)\n setScale((s) => Math.min(MAX_SCALE, s * ZOOM_STEP))\n }\n const zoomOut = () => {\n setFitToWidth(false)\n setScale((s) => Math.max(MIN_SCALE, s / ZOOM_STEP))\n }\n\n return (\n <div\n data-rendra=\"DOC-001\"\n role=\"group\"\n aria-label={title}\n className={cn(\n 'flex h-viewer min-h-0 flex-col overflow-hidden rounded-surface border bg-card',\n className,\n )}\n >\n {status === 'empty' && (\n <EmptyState title={emptyTitle} description={emptyDescription} className=\"m-auto\" />\n )}\n\n {status === 'loading' && (\n <div\n className=\"m-auto flex flex-col items-center gap-2 px-4 py-8 text-sm text-muted-foreground\"\n role=\"status\"\n >\n {loadingLabel}\n </div>\n )}\n\n {status === 'error' && (\n <EmptyState\n type=\"error\"\n title={errorTitle}\n description={errorDescription}\n className=\"m-auto\"\n actions={\n url && (\n <Button variant=\"outline\" asChild>\n <a href={url} target=\"_blank\" rel=\"noreferrer\">\n <ExternalLink aria-hidden />\n {openInNewTabLabel}\n </a>\n </Button>\n )\n }\n />\n )}\n\n {status === 'ready' && (\n <>\n <div className=\"flex shrink-0 items-center justify-between gap-3 border-b bg-card px-3 py-2\">\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={zoomOutLabel}\n icon={<ZoomOut />}\n onClick={zoomOut}\n />\n <span className=\"w-12 text-center text-xs text-muted-foreground tabular-nums\">\n {fitToWidth ? 'Ajustar' : `${Math.round(scale * 100)}%`}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={zoomInLabel}\n icon={<ZoomIn />}\n onClick={zoomIn}\n />\n </div>\n {numPages > 1 && (\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={previousPageLabel}\n icon={<ChevronLeft />}\n disabled={page <= 1}\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n />\n <span className=\"text-xs text-muted-foreground tabular-nums\" aria-live=\"polite\">\n {page} de {numPages}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n iconOnly\n aria-label={nextPageLabel}\n icon={<ChevronRight />}\n disabled={page >= numPages}\n onClick={() => setPage((p) => Math.min(numPages, p + 1))}\n />\n </div>\n )}\n </div>\n <div\n ref={containerRef}\n className=\"flex min-h-0 flex-1 items-center justify-center overflow-auto bg-muted p-4\"\n >\n <canvas ref={canvasRef} className=\"max-w-full rounded-item bg-card shadow-sm\" />\n </div>\n </>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as cn } from "./cn-
|
|
1
|
+
/*! Rendra Design System v2.6.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-TBlI6-gS.js";
|
|
3
|
+
import { i as useMotionLib } from "./motion-context-BL545cb6.js";
|
|
4
|
+
import { t as useMotionPresets } from "./use-motion-presets-DCJPBfNJ.js";
|
|
3
5
|
import { CircleCheck, CircleX, Info, TriangleAlert } from "lucide-react";
|
|
4
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { createContext, useContext } from "react";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
8
|
import { cva } from "class-variance-authority";
|
|
7
9
|
//#region src/brand/brand-context.ts
|
|
8
10
|
var BrandContext = createContext(null);
|
|
@@ -133,10 +135,10 @@ function BrandFeedbackIcon({ type, size, label, animated = false, symbolTone = "
|
|
|
133
135
|
"data-rendra": "BFI-001",
|
|
134
136
|
className: cn(sideBadge ? "relative inline-flex shrink-0 items-center gap-1" : iconVariants({ size }), rootTone, animated && !encaixe && type === "error" && "animate-shake", className),
|
|
135
137
|
...a11y,
|
|
136
|
-
children: Custom ? /* @__PURE__ */ jsx(Custom, { className: cn("size-full", symbolTonal, symbolAnim) }) : sideBadge ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Symbol, { className: cn(sizes[size ?? "md"], symbolTonal, symbolAnim) }), /* @__PURE__ */ jsx(BadgeIcon, {
|
|
138
|
+
children: Custom ? /* @__PURE__ */ jsx(Custom, { className: cn("size-full", symbolTonal, symbolAnim) }) : sideBadge ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Symbol, { className: cn(sizes[size ?? "md"], symbolTonal, symbolAnim) }), /* @__PURE__ */ jsx(BadgeIcon, {
|
|
137
139
|
"aria-hidden": true,
|
|
138
140
|
className: cn("shrink-0", badgeIconSize[size ?? "md"], stateText[type], badgeAnim)
|
|
139
|
-
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Symbol, { className: cn("size-full mask-status-cutout", symbolTonal, symbolAnim) }), /* @__PURE__ */ jsx("span", {
|
|
141
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Symbol, { className: cn("size-full mask-status-cutout", symbolTonal, symbolAnim) }), /* @__PURE__ */ jsx("span", {
|
|
140
142
|
className: cn("absolute right-0 bottom-0 flex size-1/2 items-center justify-center rounded-full", badgeTone[type], badgeAnim),
|
|
141
143
|
children: /* @__PURE__ */ jsx(StatusGlyph, {
|
|
142
144
|
type,
|
|
@@ -150,12 +152,31 @@ function BrandFeedbackIcon({ type, size, label, animated = false, symbolTone = "
|
|
|
150
152
|
//#region src/components/ui/empty-state.tsx
|
|
151
153
|
/** Estado vazio (e de erro) com o ícone de feedback da marca. */
|
|
152
154
|
function EmptyState({ title, description, type = "info", actions, size = "default", className }) {
|
|
155
|
+
const lib = useMotionLib();
|
|
156
|
+
const on = lib !== null;
|
|
157
|
+
const presets = useMotionPresets();
|
|
158
|
+
const Icon = on ? lib.m.span : "span";
|
|
159
|
+
const Title = on ? lib.m.p : "p";
|
|
160
|
+
const Description = on ? lib.m.p : "p";
|
|
161
|
+
const Actions = on ? lib.m.div : "div";
|
|
162
|
+
const part = (index) => {
|
|
163
|
+
if (!on) return {};
|
|
164
|
+
const enter = presets.slide("bottom", "short");
|
|
165
|
+
return {
|
|
166
|
+
...enter,
|
|
167
|
+
transition: {
|
|
168
|
+
...enter.transition,
|
|
169
|
+
...presets.stagger(index)
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
};
|
|
153
173
|
return /* @__PURE__ */ jsxs("div", {
|
|
154
174
|
"data-rendra": "VAZ-001",
|
|
155
175
|
className: cn("flex flex-col items-center justify-center gap-4 text-center", size === "compact" ? "px-4 py-8" : "px-4 py-12 md:py-16", className),
|
|
156
176
|
children: [
|
|
157
|
-
/* @__PURE__ */ jsxs(
|
|
177
|
+
/* @__PURE__ */ jsxs(Icon, {
|
|
158
178
|
className: "relative flex items-center justify-center",
|
|
179
|
+
...part(0),
|
|
159
180
|
children: [/* @__PURE__ */ jsx("span", {
|
|
160
181
|
"aria-hidden": true,
|
|
161
182
|
className: "absolute size-16 rounded-full bg-gradient-soft"
|
|
@@ -167,16 +188,19 @@ function EmptyState({ title, description, type = "info", actions, size = "defaul
|
|
|
167
188
|
}),
|
|
168
189
|
/* @__PURE__ */ jsxs("div", {
|
|
169
190
|
className: "flex w-full flex-col gap-1",
|
|
170
|
-
children: [/* @__PURE__ */ jsx(
|
|
171
|
-
className: "text-base font-semibold",
|
|
191
|
+
children: [/* @__PURE__ */ jsx(Title, {
|
|
192
|
+
className: "text-base font-semibold wrap-break-word",
|
|
193
|
+
...part(1),
|
|
172
194
|
children: title
|
|
173
|
-
}), description && /* @__PURE__ */ jsx(
|
|
174
|
-
className: "text-sm text-muted-foreground",
|
|
195
|
+
}), description && /* @__PURE__ */ jsx(Description, {
|
|
196
|
+
className: "text-sm wrap-break-word text-muted-foreground",
|
|
197
|
+
...part(2),
|
|
175
198
|
children: description
|
|
176
199
|
})]
|
|
177
200
|
}),
|
|
178
|
-
actions && /* @__PURE__ */ jsx(
|
|
201
|
+
actions && /* @__PURE__ */ jsx(Actions, {
|
|
179
202
|
className: "flex flex-wrap justify-center gap-3",
|
|
203
|
+
...part(3),
|
|
180
204
|
children: actions
|
|
181
205
|
})
|
|
182
206
|
]
|
|
@@ -185,4 +209,4 @@ function EmptyState({ title, description, type = "info", actions, size = "defaul
|
|
|
185
209
|
//#endregion
|
|
186
210
|
export { BrandContext as a, useBrand as i, BrandFeedbackIcon as n, feedbackLabels as r, EmptyState as t };
|
|
187
211
|
|
|
188
|
-
//# sourceMappingURL=empty-state-
|
|
212
|
+
//# sourceMappingURL=empty-state-DrQjqxvp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empty-state-CdaDLcsB.js","names":[],"sources":["../src/brand/brand-context.ts","../src/brand/use-brand.ts","../src/components/ui/brand-feedback-icon.tsx","../src/components/ui/empty-state.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { Shape } from '@/lib/shape'\nimport type { BrandConfig, PaletteConfig } from './types'\n\nexport type ColorMode = 'light' | 'dark' | 'system'\n\nexport interface BrandContextValue {\n brand: BrandConfig\n brands: BrandConfig[]\n setBrandId: (id: string) => void\n mode: ColorMode\n resolvedMode: 'light' | 'dark'\n setMode: (mode: ColorMode) => void\n /** Formato do template ativo (fixo por template). */\n shape: Shape\n /** Paleta de cores em uso (por padrão, a do próprio modelo). */\n palette: PaletteConfig\n palettes: PaletteConfig[]\n /** Usa a paleta de outro template; null volta às cores do próprio modelo. */\n setPaletteId: (id: string | null) => void\n /** Logotipo adequado para a sidebar com a paleta atual. */\n sidebarLogoVariant: 'light' | 'dark'\n}\n\nexport const BrandContext = createContext<BrandContextValue | null>(null)\n","import { useContext } from 'react'\nimport { BrandContext } from './brand-context'\n\nexport function useBrand() {\n const ctx = useContext(BrandContext)\n if (!ctx) throw new Error('useBrand precisa estar dentro de <BrandProvider>.')\n return ctx\n}\n","import { cva, type VariantProps } from 'class-variance-authority'\nimport { CircleCheck, CircleX, Info, TriangleAlert, type LucideIcon } from 'lucide-react'\nimport type { SVGProps } from 'react'\nimport { useBrand } from '@/brand/use-brand'\nimport type { FeedbackType } from '@/brand/types'\nimport { cn } from '@/lib/cn'\n\nconst sizes = {\n sm: 'size-icon-sm',\n md: 'size-icon-md',\n lg: 'size-icon-lg',\n xl: 'size-12',\n '2xl': 'size-16',\n} as const\n\nconst iconVariants = cva('relative inline-flex shrink-0', {\n variants: { size: sizes },\n defaultVariants: { size: 'md' },\n})\n\n/** Cor do estado (tinge o símbolo e, em statusBadge, o ícone ao lado). */\nconst stateText: Record<FeedbackType, string> = {\n success: 'text-success',\n error: 'text-destructive',\n warning: 'text-warning',\n info: 'text-info',\n}\n\n/** Ícone Lucide do selo ao lado do símbolo (statusBadge). */\nconst badgeIcons: Record<FeedbackType, LucideIcon> = {\n success: CircleCheck,\n error: CircleX,\n warning: TriangleAlert,\n info: Info,\n}\n\n/** Tamanho do ícone ao lado, proporcional ao do símbolo. */\nconst badgeIconSize: Record<keyof typeof sizes, string> = {\n sm: 'size-3',\n md: 'size-icon-sm',\n lg: 'size-icon-md',\n xl: 'size-icon-lg',\n '2xl': 'size-icon-lg',\n}\n\nconst badgeTone: Record<FeedbackType, string> = {\n success: 'bg-success text-success-foreground',\n error: 'bg-destructive text-destructive-foreground',\n warning: 'bg-warning text-warning-foreground',\n info: 'bg-info text-info-foreground',\n}\n\nexport const feedbackLabels: Record<FeedbackType, string> = {\n success: 'Sucesso',\n error: 'Erro',\n warning: 'Atenção',\n info: 'Informação',\n}\n\n/** Glifos universais de status desenhados em traço, herdando currentColor. */\nfunction StatusGlyph({\n type,\n animated,\n ...props\n}: { type: FeedbackType; animated?: boolean } & SVGProps<SVGSVGElement>) {\n // pathLength=1 normaliza o traço: o desenho anima de 1 a 0 em qualquer glifo.\n const draw = animated\n ? ({ pathLength: 1, strokeDasharray: 1, className: 'animate-draw' } as const)\n : {}\n const common = {\n viewBox: '0 0 12 12',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n 'aria-hidden': true,\n ...props,\n }\n switch (type) {\n case 'success':\n return (\n <svg {...common}>\n <path d=\"M3 6.2 5.1 8.2 9 4\" {...draw} />\n </svg>\n )\n case 'error':\n return (\n <svg {...common}>\n <path d=\"M4 4l4 4M8 4 4 8\" {...draw} />\n </svg>\n )\n case 'warning':\n return (\n <svg {...common}>\n <path d=\"M6 3.2v3.3M6 8.8v0\" {...draw} />\n </svg>\n )\n case 'info':\n return (\n <svg {...common}>\n <path d=\"M6 3.2v0M6 5.5v3.3\" {...draw} />\n </svg>\n )\n }\n}\n\nexport interface BrandFeedbackIconProps extends VariantProps<typeof iconVariants> {\n type: FeedbackType\n /** Texto para leitores de tela. Sem ele o ícone é decorativo (o texto ao lado informa). */\n label?: string\n /**\n * Anima a entrada: o símbolo entra com mola e o glifo se desenha (check se formando,\n * X se riscando). O erro treme ao final. Respeita reduzir movimento.\n * Troque a key do componente para repetir a animação.\n */\n animated?: boolean\n /**\n * Cor do símbolo. `state` (padrão): a cor do estado (verde, vermelho, amarelo, azul).\n * `brand`: a cor primária da marca (`text-primary-text`); o selo de estado mantém a cor do\n * estado, para o significado não depender só da cor.\n */\n symbolTone?: 'state' | 'brand'\n /**\n * `false` (padrão): selo de estado sobreposto ao símbolo. `true`: o ícone do estado\n * (Lucide, na cor do estado) fica ao lado do símbolo, no lugar do selo sobreposto. Com um\n * SVG próprio em `brand.feedbackIcons[type]`, o SVG vence e nenhum selo é desenhado.\n */\n statusBadge?: boolean\n /**\n * Só vale com `animated`. `pop` (padrão): entra com mola, o glifo se desenha e o erro\n * treme. `encaixe`: entra em 240 ms, curva de saída suave, sem quique, sem desenho e sem\n * tremor. Com \"reduzir movimento\" do sistema, nenhuma animação roda.\n */\n animation?: 'pop' | 'encaixe'\n className?: string\n}\n\n/**\n * Ícone de feedback da marca: o símbolo da marca em currentColor, tingido pela cor\n * semântica, com um selo de status para que o significado não dependa só da cor.\n * Cada tipo pode ser substituído por um SVG próprio em brand.config.ts (feedbackIcons).\n */\nexport function BrandFeedbackIcon({\n type,\n size,\n label,\n animated = false,\n symbolTone = 'state',\n statusBadge = false,\n animation = 'pop',\n className,\n}: BrandFeedbackIconProps) {\n const { brand } = useBrand()\n const Custom = brand.feedbackIcons?.[type]\n const Symbol = brand.symbol\n const a11y = label\n ? ({ role: 'img', 'aria-label': label } as const)\n : ({ 'aria-hidden': true } as const)\n const encaixe = animation === 'encaixe'\n // Com `symbolTone=\"state\"` o texto do estado fica na raiz (como sempre); com `brand` sai da raiz.\n const rootTone = symbolTone === 'state' ? stateText[type] : undefined\n const symbolTonal = symbolTone === 'brand' && 'text-primary-text'\n const symbolAnim = animated && (encaixe ? 'animate-encaixe' : 'animate-pop')\n const badgeAnim = animated && (encaixe ? 'animate-encaixe' : 'animate-pop anim-delay-1')\n const BadgeIcon = badgeIcons[type]\n const sideBadge = statusBadge && !Custom\n\n return (\n <span\n data-slot=\"feedback-icon\"\n data-rendra=\"BFI-001\"\n className={cn(\n sideBadge ? 'relative inline-flex shrink-0 items-center gap-1' : iconVariants({ size }),\n rootTone,\n animated && !encaixe && type === 'error' && 'animate-shake',\n className,\n )}\n {...a11y}\n >\n {Custom ? (\n <Custom className={cn('size-full', symbolTonal, symbolAnim)} />\n ) : sideBadge ? (\n <>\n <Symbol className={cn(sizes[size ?? 'md'], symbolTonal, symbolAnim)} />\n <BadgeIcon\n aria-hidden\n className={cn('shrink-0', badgeIconSize[size ?? 'md'], stateText[type], badgeAnim)}\n />\n </>\n ) : (\n <>\n <Symbol className={cn('size-full mask-status-cutout', symbolTonal, symbolAnim)} />\n <span\n className={cn(\n 'absolute right-0 bottom-0 flex size-1/2 items-center justify-center rounded-full',\n badgeTone[type],\n badgeAnim,\n )}\n >\n <StatusGlyph type={type} animated={animated && !encaixe} className=\"size-full\" />\n </span>\n </>\n )}\n </span>\n )\n}\n","import type { ReactNode } from 'react'\nimport type { FeedbackType } from '@/brand/types'\nimport { BrandFeedbackIcon } from '@/components/ui/brand-feedback-icon'\nimport { cn } from '@/lib/cn'\n\nexport interface EmptyStateProps {\n title: string\n description?: ReactNode\n /** Tipo do ícone de feedback da marca. info para \"sem dados\", error para falha. */\n type?: FeedbackType\n /** Ações: no máximo uma principal e uma secundária. */\n actions?: ReactNode\n /** compact: dentro de tabela ou card pequeno. */\n size?: 'default' | 'compact'\n /**\n * Classes extras, que vencem as do componente. Para zerar o respiro vertical (por exemplo,\n * dentro de um card que já tem o seu) use `className=\"py-0 md:py-0\"`.\n */\n className?: string\n}\n\n/** Estado vazio (e de erro) com o ícone de feedback da marca. */\nexport function EmptyState({\n title,\n description,\n type = 'info',\n actions,\n size = 'default',\n className,\n}: EmptyStateProps) {\n return (\n <div\n data-rendra=\"VAZ-001\"\n className={cn(\n 'flex flex-col items-center justify-center gap-4 text-center',\n size === 'compact' ? 'px-4 py-8' : 'px-4 py-12 md:py-16',\n className,\n )}\n >\n <span className=\"relative flex items-center justify-center\">\n <span aria-hidden className=\"absolute size-16 rounded-full bg-gradient-soft\" />\n <BrandFeedbackIcon\n type={type}\n size={size === 'compact' ? 'xl' : '2xl'}\n className=\"relative\"\n />\n </span>\n <div className=\"flex w-full flex-col gap-1\">\n <p className=\"text-base font-semibold\">{title}</p>\n {description && <p className=\"text-sm text-muted-foreground\">{description}</p>}\n </div>\n {actions && <div className=\"flex flex-wrap justify-center gap-3\">{actions}</div>}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"empty-state-DrQjqxvp.js","names":[],"sources":["../src/brand/brand-context.ts","../src/brand/use-brand.ts","../src/components/ui/brand-feedback-icon.tsx","../src/components/ui/empty-state.tsx"],"sourcesContent":["import { createContext } from 'react'\nimport type { Shape } from '@/lib/shape'\nimport type { BrandConfig, PaletteConfig } from './types'\n\nexport type ColorMode = 'light' | 'dark' | 'system'\n\nexport interface BrandContextValue {\n brand: BrandConfig\n brands: BrandConfig[]\n setBrandId: (id: string) => void\n mode: ColorMode\n resolvedMode: 'light' | 'dark'\n setMode: (mode: ColorMode) => void\n /** Formato do template ativo (fixo por template). */\n shape: Shape\n /** Paleta de cores em uso (por padrão, a do próprio modelo). */\n palette: PaletteConfig\n palettes: PaletteConfig[]\n /** Usa a paleta de outro template; null volta às cores do próprio modelo. */\n setPaletteId: (id: string | null) => void\n /** Logotipo adequado para a sidebar com a paleta atual. */\n sidebarLogoVariant: 'light' | 'dark'\n}\n\nexport const BrandContext = createContext<BrandContextValue | null>(null)\n","import { useContext } from 'react'\nimport { BrandContext } from './brand-context'\n\nexport function useBrand() {\n const ctx = useContext(BrandContext)\n if (!ctx) throw new Error('useBrand precisa estar dentro de <BrandProvider>.')\n return ctx\n}\n","import { cva, type VariantProps } from 'class-variance-authority'\nimport { CircleCheck, CircleX, Info, TriangleAlert, type LucideIcon } from 'lucide-react'\nimport type { SVGProps } from 'react'\nimport { useBrand } from '@/brand/use-brand'\nimport type { FeedbackType } from '@/brand/types'\nimport { cn } from '@/lib/cn'\n\nconst sizes = {\n sm: 'size-icon-sm',\n md: 'size-icon-md',\n lg: 'size-icon-lg',\n xl: 'size-12',\n '2xl': 'size-16',\n} as const\n\nconst iconVariants = cva('relative inline-flex shrink-0', {\n variants: { size: sizes },\n defaultVariants: { size: 'md' },\n})\n\n/** Cor do estado (tinge o símbolo e, em statusBadge, o ícone ao lado). */\nconst stateText: Record<FeedbackType, string> = {\n success: 'text-success',\n error: 'text-destructive',\n warning: 'text-warning',\n info: 'text-info',\n}\n\n/** Ícone Lucide do selo ao lado do símbolo (statusBadge). */\nconst badgeIcons: Record<FeedbackType, LucideIcon> = {\n success: CircleCheck,\n error: CircleX,\n warning: TriangleAlert,\n info: Info,\n}\n\n/** Tamanho do ícone ao lado, proporcional ao do símbolo. */\nconst badgeIconSize: Record<keyof typeof sizes, string> = {\n sm: 'size-3',\n md: 'size-icon-sm',\n lg: 'size-icon-md',\n xl: 'size-icon-lg',\n '2xl': 'size-icon-lg',\n}\n\nconst badgeTone: Record<FeedbackType, string> = {\n success: 'bg-success text-success-foreground',\n error: 'bg-destructive text-destructive-foreground',\n warning: 'bg-warning text-warning-foreground',\n info: 'bg-info text-info-foreground',\n}\n\nexport const feedbackLabels: Record<FeedbackType, string> = {\n success: 'Sucesso',\n error: 'Erro',\n warning: 'Atenção',\n info: 'Informação',\n}\n\n/** Glifos universais de status desenhados em traço, herdando currentColor. */\nfunction StatusGlyph({\n type,\n animated,\n ...props\n}: { type: FeedbackType; animated?: boolean } & SVGProps<SVGSVGElement>) {\n // pathLength=1 normaliza o traço: o desenho anima de 1 a 0 em qualquer glifo.\n const draw = animated\n ? ({ pathLength: 1, strokeDasharray: 1, className: 'animate-draw' } as const)\n : {}\n const common = {\n viewBox: '0 0 12 12',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n 'aria-hidden': true,\n ...props,\n }\n switch (type) {\n case 'success':\n return (\n <svg {...common}>\n <path d=\"M3 6.2 5.1 8.2 9 4\" {...draw} />\n </svg>\n )\n case 'error':\n return (\n <svg {...common}>\n <path d=\"M4 4l4 4M8 4 4 8\" {...draw} />\n </svg>\n )\n case 'warning':\n return (\n <svg {...common}>\n <path d=\"M6 3.2v3.3M6 8.8v0\" {...draw} />\n </svg>\n )\n case 'info':\n return (\n <svg {...common}>\n <path d=\"M6 3.2v0M6 5.5v3.3\" {...draw} />\n </svg>\n )\n }\n}\n\nexport interface BrandFeedbackIconProps extends VariantProps<typeof iconVariants> {\n type: FeedbackType\n /** Texto para leitores de tela. Sem ele o ícone é decorativo (o texto ao lado informa). */\n label?: string\n /**\n * Anima a entrada: o símbolo entra com mola e o glifo se desenha (check se formando,\n * X se riscando). O erro treme ao final. Respeita reduzir movimento.\n * Troque a key do componente para repetir a animação.\n */\n animated?: boolean\n /**\n * Cor do símbolo. `state` (padrão): a cor do estado (verde, vermelho, amarelo, azul).\n * `brand`: a cor primária da marca (`text-primary-text`); o selo de estado mantém a cor do\n * estado, para o significado não depender só da cor.\n */\n symbolTone?: 'state' | 'brand'\n /**\n * `false` (padrão): selo de estado sobreposto ao símbolo. `true`: o ícone do estado\n * (Lucide, na cor do estado) fica ao lado do símbolo, no lugar do selo sobreposto. Com um\n * SVG próprio em `brand.feedbackIcons[type]`, o SVG vence e nenhum selo é desenhado.\n */\n statusBadge?: boolean\n /**\n * Só vale com `animated`. `pop` (padrão): entra com mola, o glifo se desenha e o erro\n * treme. `encaixe`: entra em 240 ms, curva de saída suave, sem quique, sem desenho e sem\n * tremor. Com \"reduzir movimento\" do sistema, nenhuma animação roda.\n */\n animation?: 'pop' | 'encaixe'\n className?: string\n}\n\n/**\n * Ícone de feedback da marca: o símbolo da marca em currentColor, tingido pela cor\n * semântica, com um selo de status para que o significado não dependa só da cor.\n * Cada tipo pode ser substituído por um SVG próprio em brand.config.ts (feedbackIcons).\n */\nexport function BrandFeedbackIcon({\n type,\n size,\n label,\n animated = false,\n symbolTone = 'state',\n statusBadge = false,\n animation = 'pop',\n className,\n}: BrandFeedbackIconProps) {\n const { brand } = useBrand()\n const Custom = brand.feedbackIcons?.[type]\n const Symbol = brand.symbol\n const a11y = label\n ? ({ role: 'img', 'aria-label': label } as const)\n : ({ 'aria-hidden': true } as const)\n const encaixe = animation === 'encaixe'\n // Com `symbolTone=\"state\"` o texto do estado fica na raiz (como sempre); com `brand` sai da raiz.\n const rootTone = symbolTone === 'state' ? stateText[type] : undefined\n const symbolTonal = symbolTone === 'brand' && 'text-primary-text'\n const symbolAnim = animated && (encaixe ? 'animate-encaixe' : 'animate-pop')\n const badgeAnim = animated && (encaixe ? 'animate-encaixe' : 'animate-pop anim-delay-1')\n const BadgeIcon = badgeIcons[type]\n const sideBadge = statusBadge && !Custom\n\n return (\n <span\n data-slot=\"feedback-icon\"\n data-rendra=\"BFI-001\"\n className={cn(\n sideBadge ? 'relative inline-flex shrink-0 items-center gap-1' : iconVariants({ size }),\n rootTone,\n animated && !encaixe && type === 'error' && 'animate-shake',\n className,\n )}\n {...a11y}\n >\n {Custom ? (\n <Custom className={cn('size-full', symbolTonal, symbolAnim)} />\n ) : sideBadge ? (\n <>\n <Symbol className={cn(sizes[size ?? 'md'], symbolTonal, symbolAnim)} />\n <BadgeIcon\n aria-hidden\n className={cn('shrink-0', badgeIconSize[size ?? 'md'], stateText[type], badgeAnim)}\n />\n </>\n ) : (\n <>\n <Symbol className={cn('size-full mask-status-cutout', symbolTonal, symbolAnim)} />\n <span\n className={cn(\n 'absolute right-0 bottom-0 flex size-1/2 items-center justify-center rounded-full',\n badgeTone[type],\n badgeAnim,\n )}\n >\n <StatusGlyph type={type} animated={animated && !encaixe} className=\"size-full\" />\n </span>\n </>\n )}\n </span>\n )\n}\n","import type { ElementType, ReactNode } from 'react'\nimport type { FeedbackType } from '@/brand/types'\nimport { BrandFeedbackIcon } from '@/components/ui/brand-feedback-icon'\nimport { cn } from '@/lib/cn'\nimport { useMotionLib, useMotionPresets } from '@/lib/motion'\n\nexport interface EmptyStateProps {\n title: string\n description?: ReactNode\n /** Tipo do ícone de feedback da marca. info para \"sem dados\", error para falha. */\n type?: FeedbackType\n /** Ações: no máximo uma principal e uma secundária. */\n actions?: ReactNode\n /** compact: dentro de tabela ou card pequeno. */\n size?: 'default' | 'compact'\n /**\n * Classes extras, que vencem as do componente. Para zerar o respiro vertical (por exemplo,\n * dentro de um card que já tem o seu) use `className=\"py-0 md:py-0\"`.\n */\n className?: string\n}\n\n/** Estado vazio (e de erro) com o ícone de feedback da marca. */\nexport function EmptyState({\n title,\n description,\n type = 'info',\n actions,\n size = 'default',\n className,\n}: EmptyStateProps) {\n const lib = useMotionLib()\n const on = lib !== null\n const presets = useMotionPresets()\n // Em `on` as quatro partes (ícone, título, descrição e ações) sobem em cascata de 60 ms, cada\n // uma com o deslize curto; a raiz em si não anima. Estado vazio é cota de encanto: ocasional,\n // sem teclado no caminho. Em `off` o HTML é o de sempre.\n const Icon: ElementType = on ? lib.m.span : 'span'\n const Title: ElementType = on ? lib.m.p : 'p'\n const Description: ElementType = on ? lib.m.p : 'p'\n const Actions: ElementType = on ? lib.m.div : 'div'\n const part = (index: number) => {\n if (!on) return {}\n const enter = presets.slide('bottom', 'short')\n return { ...enter, transition: { ...enter.transition, ...presets.stagger(index) } }\n }\n return (\n <div\n data-rendra=\"VAZ-001\"\n className={cn(\n 'flex flex-col items-center justify-center gap-4 text-center',\n size === 'compact' ? 'px-4 py-8' : 'px-4 py-12 md:py-16',\n className,\n )}\n >\n <Icon className=\"relative flex items-center justify-center\" {...part(0)}>\n <span aria-hidden className=\"absolute size-16 rounded-full bg-gradient-soft\" />\n <BrandFeedbackIcon\n type={type}\n size={size === 'compact' ? 'xl' : '2xl'}\n className=\"relative\"\n />\n </Icon>\n <div className=\"flex w-full flex-col gap-1\">\n <Title className=\"text-base font-semibold wrap-break-word\" {...part(1)}>\n {title}\n </Title>\n {description && (\n <Description className=\"text-sm wrap-break-word text-muted-foreground\" {...part(2)}>\n {description}\n </Description>\n )}\n </div>\n {actions && (\n <Actions className=\"flex flex-wrap justify-center gap-3\" {...part(3)}>\n {actions}\n </Actions>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|