@fayz-ai/ui 0.15.0 → 0.17.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/dist/analytics/context.d.ts +15 -1
- package/dist/analytics/context.d.ts.map +1 -1
- package/dist/analytics/index.d.ts +1 -1
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/{chunk-J7F3Z52K.js → chunk-DFOAKWYB.js} +4 -4
- package/dist/chunk-DFOAKWYB.js.map +1 -0
- package/dist/{chunk-KD2V3TAX.js → chunk-E44WOPCR.js} +61 -49
- package/dist/chunk-E44WOPCR.js.map +1 -0
- package/dist/{chunk-FFJ2C5YH.js → chunk-HKGTF2YA.js} +41 -16
- package/dist/chunk-HKGTF2YA.js.map +1 -0
- package/dist/{chunk-NA3GE4H3.js → chunk-OBIU37AX.js} +365 -252
- package/dist/chunk-OBIU37AX.js.map +1 -0
- package/dist/{chunk-SLWTKHNY.js → chunk-Z2ITFPGL.js} +380 -83
- package/dist/chunk-Z2ITFPGL.js.map +1 -0
- package/dist/{chunk-5KMAEQA3.js → chunk-ZLPYNHXH.js} +56 -21
- package/dist/chunk-ZLPYNHXH.js.map +1 -0
- package/dist/dashboard/OnboardingWidget.d.ts +7 -1
- package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
- package/dist/dashboard/SidebarOnboarding.d.ts +7 -1
- package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -1
- package/dist/dashboard/index.js +3 -3
- package/dist/hooks/useIsWide.d.ts +16 -0
- package/dist/hooks/useIsWide.d.ts.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +278 -10
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.d.ts +25 -2
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/ModulePage.d.ts +4 -0
- package/dist/layout/ModulePage.d.ts.map +1 -1
- package/dist/layout/SaveBar.d.ts.map +1 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Topbar.d.ts +5 -1
- package/dist/layout/Topbar.d.ts.map +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +3 -3
- package/dist/primitives/checkbox.d.ts +4 -0
- package/dist/primitives/checkbox.d.ts.map +1 -1
- package/dist/primitives/index.d.ts +3 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +4 -4
- package/dist/primitives/list-view.d.ts +5 -1
- package/dist/primitives/list-view.d.ts.map +1 -1
- package/dist/primitives/modal.d.ts.map +1 -1
- package/dist/primitives/page-actions.d.ts +55 -0
- package/dist/primitives/page-actions.d.ts.map +1 -0
- package/dist/primitives/page-header.d.ts +5 -2
- package/dist/primitives/page-header.d.ts.map +1 -1
- package/dist/primitives/page-toolbar.d.ts.map +1 -1
- package/dist/primitives/refresh-button.d.ts.map +1 -1
- package/dist/primitives/row-actions.d.ts +11 -0
- package/dist/primitives/row-actions.d.ts.map +1 -0
- package/dist/primitives/whatsapp-icon.d.ts +7 -0
- package/dist/primitives/whatsapp-icon.d.ts.map +1 -0
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/layout.store.d.ts +1 -0
- package/dist/stores/layout.store.d.ts.map +1 -1
- package/dist/stores/page-header.store.d.ts +39 -5
- package/dist/stores/page-header.store.d.ts.map +1 -1
- package/dist/styles.css +188 -3
- package/dist/tour/TourSpotlight.d.ts +29 -0
- package/dist/tour/TourSpotlight.d.ts.map +1 -0
- package/dist/tour/index.d.ts +4 -0
- package/dist/tour/index.d.ts.map +1 -0
- package/dist/tour/tour.store.d.ts +22 -0
- package/dist/tour/tour.store.d.ts.map +1 -0
- package/dist/tour/types.d.ts +28 -0
- package/dist/tour/types.d.ts.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-5KMAEQA3.js.map +0 -1
- package/dist/chunk-FFJ2C5YH.js.map +0 -1
- package/dist/chunk-J7F3Z52K.js.map +0 -1
- package/dist/chunk-KD2V3TAX.js.map +0 -1
- package/dist/chunk-NA3GE4H3.js.map +0 -1
- package/dist/chunk-SLWTKHNY.js.map +0 -1
package/dist/styles.css
CHANGED
|
@@ -618,12 +618,33 @@ select.bg-card,
|
|
|
618
618
|
to { opacity: 0; transform: translateX(-100%); }
|
|
619
619
|
}
|
|
620
620
|
|
|
621
|
-
/* Command palette animation
|
|
621
|
+
/* Command palette animation.
|
|
622
|
+
The desktop card is centred with translateX(-50%), so its keyframes have to
|
|
623
|
+
carry that translate or the animation snaps it back to the left edge. On a
|
|
624
|
+
phone the palette is full-bleed and centres nothing — the same keyframes
|
|
625
|
+
dragged it half a screen off. Two animations, split at the same breakpoint
|
|
626
|
+
the layout is. */
|
|
622
627
|
.saas-cmd-palette[data-state="open"] {
|
|
623
|
-
animation: saas-cmd-in 200ms ease-out both;
|
|
628
|
+
animation: saas-cmd-in-sheet 200ms ease-out both;
|
|
624
629
|
}
|
|
625
630
|
.saas-cmd-palette[data-state="closed"] {
|
|
626
|
-
animation: saas-cmd-out 150ms ease-in both;
|
|
631
|
+
animation: saas-cmd-out-sheet 150ms ease-in both;
|
|
632
|
+
}
|
|
633
|
+
@keyframes saas-cmd-in-sheet {
|
|
634
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
635
|
+
to { opacity: 1; transform: translateY(0); }
|
|
636
|
+
}
|
|
637
|
+
@keyframes saas-cmd-out-sheet {
|
|
638
|
+
from { opacity: 1; transform: translateY(0); }
|
|
639
|
+
to { opacity: 0; transform: translateY(8px); }
|
|
640
|
+
}
|
|
641
|
+
@media (min-width: 640px) {
|
|
642
|
+
.saas-cmd-palette[data-state="open"] {
|
|
643
|
+
animation: saas-cmd-in 200ms ease-out both;
|
|
644
|
+
}
|
|
645
|
+
.saas-cmd-palette[data-state="closed"] {
|
|
646
|
+
animation: saas-cmd-out 150ms ease-in both;
|
|
647
|
+
}
|
|
627
648
|
}
|
|
628
649
|
@keyframes saas-cmd-in {
|
|
629
650
|
from { opacity: 0; transform: translateX(-50%) scale(0.96) translateY(-8px); }
|
|
@@ -766,6 +787,18 @@ select.bg-card,
|
|
|
766
787
|
/* A field that spans the row it is on, whatever the column count is. */
|
|
767
788
|
.fz-field-wide { grid-column: 1 / -1; }
|
|
768
789
|
|
|
790
|
+
/* A required field that was empty when somebody pressed save.
|
|
791
|
+
*
|
|
792
|
+
* One rule here rather than a Tailwind string at each of the six form layouts —
|
|
793
|
+
* the marker travels with the field, and a layout added tomorrow gets it free.
|
|
794
|
+
* The ring is on the CONTROL, not the wrapper, so the label and the message
|
|
795
|
+
* either side of it stay legible. */
|
|
796
|
+
.fz-field-invalid :is(input, textarea, select, [role='combobox'], [contenteditable='true']) {
|
|
797
|
+
border-color: hsl(var(--destructive));
|
|
798
|
+
box-shadow: 0 0 0 1px hsl(var(--destructive) / 0.35);
|
|
799
|
+
}
|
|
800
|
+
.fz-field-invalid > label { color: hsl(var(--destructive)); }
|
|
801
|
+
|
|
769
802
|
/* Rows separated by a rule while they are stacked; side by side the rule is
|
|
770
803
|
drawn between unrelated neighbours, so it goes. */
|
|
771
804
|
@container (min-width: 30rem) {
|
|
@@ -813,3 +846,155 @@ select.bg-card,
|
|
|
813
846
|
@media (pointer: coarse) {
|
|
814
847
|
.fz-tap { min-height: 2.75rem; min-width: 2.75rem; }
|
|
815
848
|
}
|
|
849
|
+
|
|
850
|
+
/* ---------------------------------------------------------------------------
|
|
851
|
+
Mobile platform baseline
|
|
852
|
+
The shell renders inside Safari and Chrome on a phone, not just inside a
|
|
853
|
+
desktop viewport that happens to be narrow. These rules cover the platform
|
|
854
|
+
behaviours the browser applies on its own unless told otherwise.
|
|
855
|
+
--------------------------------------------------------------------------- */
|
|
856
|
+
|
|
857
|
+
/* Double-tap-to-zoom costs every tap a 300ms wait while the browser decides
|
|
858
|
+
whether a second tap is coming. `manipulation` opts out of that gesture and
|
|
859
|
+
keeps pinch-to-zoom, which is an accessibility guarantee we do not take away. */
|
|
860
|
+
html {
|
|
861
|
+
touch-action: manipulation;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/* iOS zooms the whole page when a field smaller than 16px takes focus, and
|
|
865
|
+
never zooms back. Anything a finger can focus gets 16px, on touch INPUT
|
|
866
|
+
rather than screen width — an iPad zooms exactly like a phone. Fields that
|
|
867
|
+
are deliberately larger keep their size. */
|
|
868
|
+
@media (pointer: coarse) {
|
|
869
|
+
input:not([type='checkbox'], [type='radio']),
|
|
870
|
+
textarea:not([hidden]),
|
|
871
|
+
select:not([hidden]) {
|
|
872
|
+
font-size: max(16px, 1em);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/* WebKit paints a grey flash over any tapped element. Suppress it and let the
|
|
877
|
+
component's own :active state be the feedback, so a tap never looks like it
|
|
878
|
+
selected a block of the page. */
|
|
879
|
+
* {
|
|
880
|
+
-webkit-tap-highlight-color: transparent;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/* A scroller that reaches its end hands the gesture to the page behind it —
|
|
884
|
+
which on mobile means a drawer, sheet or chat transcript can rubber-band the
|
|
885
|
+
whole app or trigger pull-to-refresh mid-scroll. */
|
|
886
|
+
.fz-scroll-contain {
|
|
887
|
+
overscroll-behavior: contain;
|
|
888
|
+
-webkit-overflow-scrolling: touch;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/* The notch, the Dynamic Island and the home indicator all sit inside the
|
|
892
|
+
viewport once `viewport-fit=cover` is set. Fixed chrome has to pad itself out
|
|
893
|
+
of them; env() resolves to 0 everywhere else, so these are safe on desktop. */
|
|
894
|
+
.fz-safe-b { padding-bottom: env(safe-area-inset-bottom); }
|
|
895
|
+
.fz-safe-t { padding-top: env(safe-area-inset-top); }
|
|
896
|
+
.fz-safe-x {
|
|
897
|
+
padding-left: env(safe-area-inset-left);
|
|
898
|
+
padding-right: env(safe-area-inset-right);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/* `100vh` on mobile means the viewport with the browser chrome hidden, which is
|
|
902
|
+
taller than what the user can actually see — the bottom of a vh-sized shell
|
|
903
|
+
sits under the address bar. `dvh` tracks the visible height instead; the vh
|
|
904
|
+
line stays as the fallback for browsers without it. */
|
|
905
|
+
.fz-viewport-h {
|
|
906
|
+
height: 100vh;
|
|
907
|
+
height: 100dvh;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/* How much of the bottom of the screen the tab bar owns. Anything that floats
|
|
911
|
+
above the fold — the save bar, toasts, a sheet handle — offsets by this
|
|
912
|
+
instead of hardcoding the bar's height, so it still sits right on a layout
|
|
913
|
+
that has no bar. Zero unless the shell says otherwise. */
|
|
914
|
+
:root { --fz-bottom-bar: 0px; }
|
|
915
|
+
@media (max-width: 767px) {
|
|
916
|
+
.fz-has-bottom-bar { --fz-bottom-bar: calc(4rem + env(safe-area-inset-bottom)); }
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/* ---------------------------------------------------------------------------
|
|
920
|
+
Stacking order
|
|
921
|
+
Transient surfaces have to clear the shell's own fixed chrome. The mobile
|
|
922
|
+
navigation drawer sits at 60, so a menu at the Tailwind default of 50 opens
|
|
923
|
+
BEHIND it and reads as a dead control — which is exactly what happened to the
|
|
924
|
+
tenant switcher, the user menu and notifications inside the drawer.
|
|
925
|
+
|
|
926
|
+
50 bottom tab bar
|
|
927
|
+
55 save bar (above the tab bar, below anything modal)
|
|
928
|
+
60 nav drawer, right rail
|
|
929
|
+
100 modal, sheet (covers the drawer that opened it)
|
|
930
|
+
110 dropdown, select, popover
|
|
931
|
+
120 tooltip (above a modal it is anchored inside)
|
|
932
|
+
--------------------------------------------------------------------------- */
|
|
933
|
+
|
|
934
|
+
/* ---------------------------------------------------------------------------
|
|
935
|
+
FAB speed-dial
|
|
936
|
+
A menu opening from a thumb-corner button wants to look like it came OUT of
|
|
937
|
+
that button. The shared dropdown enter (fade + 2px slide) is right for a menu
|
|
938
|
+
anchored to a toolbar and reads as instant from a 56px circle in the corner.
|
|
939
|
+
--------------------------------------------------------------------------- */
|
|
940
|
+
|
|
941
|
+
.fz-fab-menu[data-state='open'] {
|
|
942
|
+
animation: fz-fab-menu-in 220ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
943
|
+
transform-origin: bottom right;
|
|
944
|
+
}
|
|
945
|
+
.fz-fab-menu[data-state='closed'] {
|
|
946
|
+
animation: fz-fab-menu-out 130ms ease-in both;
|
|
947
|
+
transform-origin: bottom right;
|
|
948
|
+
}
|
|
949
|
+
@keyframes fz-fab-menu-in {
|
|
950
|
+
from { opacity: 0; transform: translateY(12px) scale(0.92); }
|
|
951
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
952
|
+
}
|
|
953
|
+
@keyframes fz-fab-menu-out {
|
|
954
|
+
from { opacity: 1; transform: translateY(0) scale(1); }
|
|
955
|
+
to { opacity: 0; transform: translateY(8px) scale(0.96); }
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/* Items arrive in the order they are read, just behind the panel. */
|
|
959
|
+
.fz-fab-menu[data-state='open'] .fz-fab-item {
|
|
960
|
+
animation: fz-fab-item-in 200ms ease-out both;
|
|
961
|
+
animation-delay: calc(60ms + var(--i, 0) * 40ms);
|
|
962
|
+
}
|
|
963
|
+
@keyframes fz-fab-item-in {
|
|
964
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
965
|
+
to { opacity: 1; transform: translateY(0); }
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/* The "+" becomes an "×" while the menu is open — the button says what tapping
|
|
969
|
+
it again will do. */
|
|
970
|
+
.fz-fab-trigger svg { transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1); }
|
|
971
|
+
.fz-fab-trigger[data-state='open'] svg { transform: rotate(135deg); }
|
|
972
|
+
|
|
973
|
+
@media (prefers-reduced-motion: reduce) {
|
|
974
|
+
.fz-fab-menu[data-state='open'],
|
|
975
|
+
.fz-fab-menu[data-state='closed'],
|
|
976
|
+
.fz-fab-menu[data-state='open'] .fz-fab-item { animation: none; }
|
|
977
|
+
.fz-fab-trigger svg { transition: none; }
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/* ---------------------------------------------------------------------------
|
|
981
|
+
Guided tour — the light on the control.
|
|
982
|
+
A hard double ring read as a validation error drawn around a button. This is
|
|
983
|
+
a soft halo that breathes instead: the movement is what says "this one, now",
|
|
984
|
+
and it is the only thing moving on a dimmed screen, so it can be gentle.
|
|
985
|
+
--------------------------------------------------------------------------- */
|
|
986
|
+
@keyframes fz-spotlight-breathe {
|
|
987
|
+
0%, 100% { box-shadow: 0 0 0 2px hsl(var(--primary) / 0.55), 0 0 0 7px hsl(var(--primary) / 0.14); }
|
|
988
|
+
50% { box-shadow: 0 0 0 3px hsl(var(--primary) / 0.75), 0 0 0 12px hsl(var(--primary) / 0.06); }
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
.fz-spotlight-ring {
|
|
992
|
+
border-radius: 12px;
|
|
993
|
+
box-shadow: 0 0 0 2px hsl(var(--primary) / 0.55), 0 0 0 7px hsl(var(--primary) / 0.14);
|
|
994
|
+
animation: fz-spotlight-breathe 2.4s ease-in-out infinite;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
@media (prefers-reduced-motion: reduce) {
|
|
998
|
+
/* Still marked, just not moving. */
|
|
999
|
+
.fz-spotlight-ring { animation: none; }
|
|
1000
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface TourSpotlightProps {
|
|
3
|
+
labels?: Partial<typeof DEFAULT_LABELS>;
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const DEFAULT_LABELS: {
|
|
7
|
+
next: string;
|
|
8
|
+
waiting: string;
|
|
9
|
+
back: string;
|
|
10
|
+
done: string;
|
|
11
|
+
skip: string;
|
|
12
|
+
stepOf: string;
|
|
13
|
+
notFound: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The tour overlay: dim everything, cut a hole around one element, and put a
|
|
17
|
+
* label next to it.
|
|
18
|
+
*
|
|
19
|
+
* The hole is FOUR dim panels rather than one panel with a mask, and that is the
|
|
20
|
+
* whole trick: a masked overlay still swallows the click, so the "click New
|
|
21
|
+
* product" stop would highlight a button nobody could press. With four panels
|
|
22
|
+
* the hole is genuinely empty — the element underneath stays live, and somebody
|
|
23
|
+
* being taught to use the app can actually use it while being taught.
|
|
24
|
+
*
|
|
25
|
+
* Mounted once by the shell. It renders nothing until a tour is running.
|
|
26
|
+
*/
|
|
27
|
+
export declare function TourSpotlight({ labels, className }: TourSpotlightProps): React.ReactPortal | null;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=TourSpotlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TourSpotlight.d.ts","sourceRoot":"","sources":["../../src/tour/TourSpotlight.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,cAAc,CAAC,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,cAAc;;;;;;;;CAQnB,CAAA;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,kBAAkB,4BAyLtE"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { TourSpotlight, type TourSpotlightProps } from './TourSpotlight';
|
|
2
|
+
export { useTourStore, setTourNavigator, getTourNavigator, currentStop, type TourState } from './tour.store';
|
|
3
|
+
export { tourAnchor, type TourDef, type TourStopDef } from './types';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tour/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAC5G,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TourDef, TourStopDef } from './types';
|
|
2
|
+
export declare function setTourNavigator(fn: ((path: string) => void) | undefined): void;
|
|
3
|
+
export declare function getTourNavigator(): ((path: string) => void) | undefined;
|
|
4
|
+
export interface TourState {
|
|
5
|
+
tour: TourDef | null;
|
|
6
|
+
index: number;
|
|
7
|
+
/** Why the last tour ended — read by whoever started it (the agent reports back). */
|
|
8
|
+
lastOutcome: {
|
|
9
|
+
tourId: string;
|
|
10
|
+
completed: boolean;
|
|
11
|
+
} | null;
|
|
12
|
+
start: (tour: TourDef) => void;
|
|
13
|
+
next: () => void;
|
|
14
|
+
prev: () => void;
|
|
15
|
+
goTo: (index: number) => void;
|
|
16
|
+
/** `completed` distinguishes finishing from skipping; both close the overlay. */
|
|
17
|
+
stop: (completed?: boolean) => void;
|
|
18
|
+
}
|
|
19
|
+
export declare const useTourStore: import("zustand").UseBoundStore<import("zustand").StoreApi<TourState>>;
|
|
20
|
+
/** The stop on screen right now, if any. */
|
|
21
|
+
export declare function currentStop(state: TourState): TourStopDef | undefined;
|
|
22
|
+
//# sourceMappingURL=tour.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tour.store.d.ts","sourceRoot":"","sources":["../../src/tour/tour.store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAcnD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAE/E;AACD,wBAAgB,gBAAgB,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAEvE;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IAC1D,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,iFAAiF;IACjF,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACpC;AAED,eAAO,MAAM,YAAY,wEA8BtB,CAAA;AAEH,4CAA4C;AAC5C,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAErE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tour shapes.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `TourDef` in @fayz-ai/core so the UI kit stays importable on its own
|
|
5
|
+
* (it does not depend on core), and so a plugin's declared tour and a tour the
|
|
6
|
+
* agent invents at runtime are the same object.
|
|
7
|
+
*/
|
|
8
|
+
export interface TourStopDef {
|
|
9
|
+
/** Matches `data-tour="<anchor>"` in the document. */
|
|
10
|
+
anchor: string;
|
|
11
|
+
title: string;
|
|
12
|
+
body?: string;
|
|
13
|
+
/** Navigate here before looking for the anchor. */
|
|
14
|
+
route?: string;
|
|
15
|
+
placement?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
|
|
16
|
+
/** Wait for the person to use the control instead of offering "next". */
|
|
17
|
+
waitForUser?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface TourDef {
|
|
20
|
+
id: string;
|
|
21
|
+
title?: string;
|
|
22
|
+
stops: TourStopDef[];
|
|
23
|
+
}
|
|
24
|
+
/** Spread onto the element a tour points at: `<Button {...tourAnchor('shop.new')} />`. */
|
|
25
|
+
export declare function tourAnchor(anchor: string): {
|
|
26
|
+
'data-tour': string;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tour/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAA;IACxD,yEAAyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,WAAW,EAAE,CAAA;CACrB;AAED,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAElE"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"fayz": {
|
|
4
4
|
"status": "beta"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.17.0",
|
|
7
7
|
"description": "Fayz SDK UI — Radix + Tailwind component library with CRUD engine and layout shells",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": [
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"clsx": "^2.1.0",
|
|
80
80
|
"recharts": "^2.15.0",
|
|
81
81
|
"tailwind-merge": "^2.4.0",
|
|
82
|
-
"@fayz-ai/core": "^0.
|
|
82
|
+
"@fayz-ai/core": "^0.17.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@types/react": "^18.3.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dashboard/DashboardGrid.tsx","../src/dashboard/layout.ts","../src/dashboard/preferences.ts","../src/dashboard/DashboardRange.tsx","../src/dashboard/DashboardCustomizeMenu.tsx","../src/dashboard/DashboardCanvas.tsx","../src/dashboard/GoldCard.tsx","../src/dashboard/icon.ts","../src/dashboard/Sparkline.tsx","../src/dashboard/KpiCard.tsx","../src/dashboard/ChartWidget.tsx","../src/dashboard/TableWidget.tsx","../src/dashboard/useOnboardingProgress.ts","../src/dashboard/OnboardingWidget.tsx","../src/dashboard/SidebarOnboarding.tsx","../src/dashboard/define.ts"],"names":["React2","jsx","jsxs","Component","React3","React4","React5","React6","React7","Fragment","React8","React9","React10","Check","Circle"],"mappings":"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","file":"chunk-5KMAEQA3.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface DashboardGridItem {\n id: string\n /** Column span on the 4-col grid (defaults to 1). */\n span?: number\n node: React.ReactNode\n}\n\n/** Literal span → Tailwind classes (kept literal so the JIT compiler picks them up). */\nconst SPAN_CLASS: Record<number, string> = {\n 1: '',\n 2: 'sm:col-span-2',\n 3: 'sm:col-span-2 lg:col-span-3',\n 4: 'sm:col-span-2 lg:col-span-4',\n}\n\nexport interface DashboardGridProps {\n items: DashboardGridItem[]\n className?: string\n}\n\n/** Responsive 4-col dashboard grid — the layout every dashboard shares. */\nexport function DashboardGrid({ items, className }: DashboardGridProps) {\n return (\n <div className={cn('grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4', className)}>\n {items.map((item) => (\n <div key={item.id} className={SPAN_CLASS[Math.min(Math.max(item.span ?? 1, 1), 4)] ?? ''}>\n {item.node}\n </div>\n ))}\n </div>\n )\n}\n","import type { DashboardLayoutConfig, DashboardWidgetDef } from '@fayz-ai/core'\n\nexport interface LaidOutWidget {\n def: DashboardWidgetDef\n /** Effective span after applying overrides (1–4). */\n span: number\n order: number\n}\n\n/**\n * Resolve the widgets to render on a surface, in order, applying three layers:\n * 1. registration defaults (defaultVisible / defaultOrder / span)\n * 2. app config (the app curates the home surface)\n * 3. user preferences (show/hide/reorder — read but currently empty)\n *\n * Later layers win. Returns only visible widgets, sorted by effective order.\n * Accepts any DashboardWidgetDef (registry-resolved or shim-built).\n */\nexport function resolveDashboardLayout(\n registered: DashboardWidgetDef[],\n appConfig?: DashboardLayoutConfig,\n userPrefs?: DashboardLayoutConfig,\n /** When true, widgets are visible by default regardless of their\n * `defaultVisible` (used on a plugin-home to show everything; the global\n * home leaves this false so `defaultVisible:false` curates the start set). */\n forceVisibleByDefault = false,\n): LaidOutWidget[] {\n type Override = { visible?: boolean; order?: number; span?: number }\n const overrides = new Map<string, Override>()\n const merge = (cfg?: DashboardLayoutConfig) => {\n for (const w of cfg?.widgets ?? []) {\n overrides.set(w.id, { ...overrides.get(w.id), ...w })\n }\n }\n merge(appConfig)\n merge(userPrefs)\n\n return registered\n .map((def, index) => {\n const o = overrides.get(def.id)\n const baseVisible = forceVisibleByDefault ? true : (def.defaultVisible ?? true)\n const visible = o?.visible ?? baseVisible\n const order = o?.order ?? def.defaultOrder ?? index\n const span = Math.min(Math.max(o?.span ?? def.span ?? 1, 1), 4)\n return { def, visible, order, span }\n })\n .filter((x) => x.visible)\n .sort((a, b) => a.order - b.order)\n .map(({ def, span, order }) => ({ def, span, order }))\n}\n","import * as React from 'react'\nimport type { DashboardLayoutConfig, DashboardSurface } from '@fayz-ai/core'\n\nexport interface DashboardPreferencesState {\n /** User-level layout overrides for this surface (null when none saved). */\n prefs: DashboardLayoutConfig | null\n /** Persist updated overrides. */\n save: (next: DashboardLayoutConfig) => void\n /** Toggle a single widget's visibility and persist. */\n setVisible: (widgetId: string, visible: boolean) => void\n /** Clear all overrides (reset to registration + app defaults). */\n reset: () => void\n}\n\nconst KEY = (surface: DashboardSurface, scope: string) => `fayz.dashboard.prefs.${scope}.${surface}`\n\nfunction read(key: string): DashboardLayoutConfig | null {\n if (typeof window === 'undefined') return null\n try {\n const raw = window.localStorage.getItem(key)\n return raw ? (JSON.parse(raw) as DashboardLayoutConfig) : null\n } catch {\n return null\n }\n}\n\n/**\n * Per-user dashboard preferences, persisted to localStorage.\n *\n * `scope` lets a plugin-home keep its own prefs separate from the global home\n * (pass the domain). A future pass can swap the storage for the tenant/plugin\n * binding store without touching callers — `resolveDashboardLayout` already\n * consumes whatever this returns as the `userPrefs` layer.\n */\nexport function useDashboardPreferences(surface: DashboardSurface, scope = 'home'): DashboardPreferencesState {\n const key = KEY(surface, scope)\n const [prefs, setPrefs] = React.useState<DashboardLayoutConfig | null>(() => read(key))\n\n // Re-read when the target surface/scope changes.\n React.useEffect(() => { setPrefs(read(key)) }, [key])\n\n const save = React.useCallback((next: DashboardLayoutConfig) => {\n setPrefs(next)\n if (typeof window !== 'undefined') {\n try { window.localStorage.setItem(key, JSON.stringify(next)) } catch { /* ignore quota/availability */ }\n }\n }, [key])\n\n const setVisible = React.useCallback((widgetId: string, visible: boolean) => {\n setPrefs((cur) => {\n const widgets = [...(cur?.widgets ?? [])]\n const i = widgets.findIndex((w) => w.id === widgetId)\n if (i >= 0) widgets[i] = { ...widgets[i]!, visible }\n else widgets.push({ id: widgetId, visible })\n const next = { ...cur, widgets }\n if (typeof window !== 'undefined') {\n try { window.localStorage.setItem(key, JSON.stringify(next)) } catch { /* ignore */ }\n }\n return next\n })\n }, [key])\n\n const reset = React.useCallback(() => {\n setPrefs(null)\n if (typeof window !== 'undefined') {\n try { window.localStorage.removeItem(key) } catch { /* ignore */ }\n }\n }, [key])\n\n return { prefs, save, setVisible, reset }\n}\n","import * as React from 'react'\nimport { RangeControl } from '../primitives/page-toolbar'\n\n// ---------------------------------------------------------------------------\n// Shared dashboard time range. The canvas provides it; widgets read it via\n// useDashboardRange() and refetch/filter their data accordingly.\n// ---------------------------------------------------------------------------\n\nexport type DashboardRange = string\n\nexport const DEFAULT_RANGE_OPTIONS: DashboardRange[] = ['7d', '30d', '90d']\n\ninterface DashboardRangeContextValue {\n range: DashboardRange\n setRange: (range: DashboardRange) => void\n options: DashboardRange[]\n}\n\nconst DashboardRangeContext = React.createContext<DashboardRangeContextValue | null>(null)\n\n/**\n * Read the shared dashboard range. Returns null when no range control is\n * mounted, so widgets can stay range-agnostic.\n */\nexport function useDashboardRange(): DashboardRangeContextValue | null {\n return React.useContext(DashboardRangeContext)\n}\n\nexport interface DashboardRangeProviderProps {\n options?: DashboardRange[]\n defaultRange?: DashboardRange\n onChange?: (range: DashboardRange) => void\n children: React.ReactNode\n}\n\nexport function DashboardRangeProvider({\n options = DEFAULT_RANGE_OPTIONS, defaultRange, onChange, children,\n}: DashboardRangeProviderProps) {\n const [range, setRangeState] = React.useState<DashboardRange>(defaultRange ?? options[1] ?? options[0] ?? '30d')\n const setRange = React.useCallback((r: DashboardRange) => {\n setRangeState(r)\n onChange?.(r)\n }, [onChange])\n const value = React.useMemo(() => ({ range, setRange, options }), [range, setRange, options])\n return <DashboardRangeContext.Provider value={value}>{children}</DashboardRangeContext.Provider>\n}\n\n/**\n * O período do dashboard, no MESMO controle que as Análises usam.\n *\n * Era um segmentado de 7d/30d/90d aqui e um menu de presets lá: a mesma escolha\n * com duas gramáticas, e mudar de tela mudava o desenho sem mudar o que se faz.\n * O segmentado (SegmentedControl) continua sendo o certo para uma alternância\n * DENTRO de um cartão — não para a pergunta que a página inteira responde.\n */\nexport function DashboardRangeControl({ className }: { className?: string }) {\n const ctx = useDashboardRange()\n if (!ctx) return null\n return (\n <RangeControl\n className={className}\n options={ctx.options.map((o) => ({ value: o, label: o }))}\n value={ctx.range}\n onChange={ctx.setRange}\n />\n )\n}\n","import * as React from 'react'\nimport { SlidersHorizontal, RotateCcw } from 'lucide-react'\nimport type { DashboardWidgetDef } from '@fayz-ai/core'\nimport { useTranslation } from '@fayz-ai/core'\nimport { ToolbarButton } from '../primitives/page-toolbar'\nimport {\n Dropdown, DropdownTrigger, DropdownContent, DropdownLabel, DropdownSeparator, DropdownCheckboxItem, DropdownItem,\n} from '../primitives/dropdown'\n\nexport interface DashboardCustomizeMenuProps {\n /** Full set of registered widgets for this surface. */\n widgets: DashboardWidgetDef[]\n /** Ids currently visible. */\n visibleIds: Set<string>\n onToggle: (widgetId: string, visible: boolean) => void\n onReset: () => void\n label?: string\n}\n\n/** Gear menu to choose which widgets appear on the dashboard (persisted). */\nexport function DashboardCustomizeMenu({ widgets, visibleIds, onToggle, onReset, label }: DashboardCustomizeMenuProps) {\n const t = useTranslation()\n if (widgets.length === 0) return null\n return (\n <Dropdown>\n <DropdownTrigger asChild>\n {/* Mesmo gatilho do período e dos filtros: é um controle da mesma barra\n e respondia com outro desenho. */}\n <ToolbarButton icon={SlidersHorizontal}>{label ?? 'Customize'}</ToolbarButton>\n </DropdownTrigger>\n <DropdownContent align=\"end\" className=\"max-h-[70vh] w-60 overflow-y-auto\">\n <DropdownLabel>{label ?? 'Show widgets'}</DropdownLabel>\n <DropdownSeparator />\n {widgets.map((w) => (\n <DropdownCheckboxItem\n key={w.id}\n checked={visibleIds.has(w.id)}\n onCheckedChange={(checked) => onToggle(w.id, Boolean(checked))}\n onSelect={(e) => e.preventDefault()}\n >\n {t(w.title)}\n </DropdownCheckboxItem>\n ))}\n <DropdownSeparator />\n <DropdownItem onSelect={() => onReset()}>\n <RotateCcw className=\"mr-2 h-3.5 w-3.5\" />\n {'Reset to defaults'}\n </DropdownItem>\n </DropdownContent>\n </Dropdown>\n )\n}\n","import * as React from 'react'\nimport { EyeOff } from 'lucide-react'\nimport {\n usePluginRuntime,\n getDashboardWidgets,\n resolvePluginComponent,\n hashRouterAdapter,\n type DashboardLayoutConfig,\n type DashboardSurface,\n type DashboardWidgetDef,\n} from '@fayz-ai/core'\nimport { cn } from '../lib/cn'\nimport { Card, CardHeader, CardTitle, CardDescription, CardContent } from '../primitives/card'\nimport { DashboardGrid, type DashboardGridItem } from './DashboardGrid'\nimport { resolveDashboardLayout, type LaidOutWidget } from './layout'\nimport { useDashboardPreferences } from './preferences'\nimport { DashboardRangeProvider, DashboardRangeControl, type DashboardRange } from './DashboardRange'\nimport { DashboardCustomizeMenu } from './DashboardCustomizeMenu'\nimport { PageToolbar } from '../primitives/page-toolbar'\nimport { useHasPageHeaderHost } from '../stores/page-header.store'\n\n/** Wrap a widget so a hide button fades in on hover (top-right corner). */\nfunction HoverHide({ id, onHide, children }: { id: string; onHide?: (id: string) => void; children: React.ReactNode }) {\n if (!onHide) return <>{children}</>\n return (\n <div className=\"group relative h-full\">\n {children}\n <button\n type=\"button\"\n onClick={() => onHide(id)}\n title=\"Hide widget\"\n aria-label=\"Hide widget\"\n className=\"absolute right-2 top-2 z-10 inline-flex h-6 w-6 items-center justify-center rounded-md border border-border bg-background/90 text-muted-foreground opacity-0 shadow-sm transition-opacity hover:text-foreground group-hover:opacity-100\"\n >\n <EyeOff className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )\n}\n\nfunction toGridItems(laidOut: LaidOutWidget[], onHide?: (id: string) => void): DashboardGridItem[] {\n return laidOut.map(({ def, span }) => {\n const Component = resolvePluginComponent(def)\n const node = Component ? <Component {...(def.props ?? {})} /> : null\n return { id: def.id, span, node: <HoverHide id={def.id} onHide={onHide}>{node}</HoverHide> }\n })\n}\n\n// ---------------------------------------------------------------------------\n// Navigation — widgets (e.g. onboarding) call useDashboardNavigate() to route.\n// Defaults to the shared hash router so widgets work without explicit wiring.\n// ---------------------------------------------------------------------------\n\nconst DashboardNavigateContext = React.createContext<(path: string) => void>((path) =>\n hashRouterAdapter().navigate(path),\n)\n\nexport const DashboardNavigateProvider = DashboardNavigateContext.Provider\n\nexport function useDashboardNavigate(): (path: string) => void {\n return React.useContext(DashboardNavigateContext)\n}\n\n// ---------------------------------------------------------------------------\n// Shared widget grid — used by DashboardCanvas (registry) and by standalone\n// callers (e.g. the dashboard plugin's legacy DashboardPage shim). Resolves the\n// layout, then renders each widget by span.\n// ---------------------------------------------------------------------------\n\nexport function WidgetGrid({ widgets, appLayout, surface }: {\n widgets: DashboardWidgetDef[]\n appLayout?: DashboardLayoutConfig\n surface: DashboardSurface\n}) {\n const { prefs, setVisible } = useDashboardPreferences(surface)\n const laidOut = resolveDashboardLayout(widgets, appLayout, prefs ?? undefined)\n return <DashboardGrid items={toGridItems(laidOut, (id) => setVisible(id, false))} />\n}\n\n// ---------------------------------------------------------------------------\n// DashboardCanvas — the registry-driven renderer. Serves the global app home\n// (surface=\"home\", all domains) and a plugin's own overview (surface=\"plugin-home\"\n// + domain). Widgets a plugin registers once appear on both.\n// ---------------------------------------------------------------------------\n\nexport interface DashboardCanvasProps {\n surface: DashboardSurface\n /** Restrict to one plugin's widgets (used for plugin-home). */\n domain?: string\n title?: string\n subtitle?: string\n /** Render the in-content title/subtitle. Default: true. */\n showHeader?: boolean\n /** App-level curation of which widgets show, their order and span. */\n appLayout?: DashboardLayoutConfig\n /** App-level widgets injected into this surface's grid without a plugin — e.g.\n * an \"Ask the assistant\" CTA. Merged with the registry widgets, then laid out\n * (respects each widget's span/defaultOrder). Filtered to this surface. */\n extraWidgets?: DashboardWidgetDef[]\n /** Show a shared time-range control (sticky, top-right). Widgets read it via\n * useDashboardRange(). Pass `true` for defaults or an options object. */\n range?: boolean | DashboardRangeOptions\n /** Show the \"Customize\" menu so users can choose which widgets appear\n * (persisted per surface). Default: true. */\n customizable?: boolean\n /** Label for the customize menu trigger. */\n customizeLabel?: string\n /** Initial visibility before user prefs: 'default' honors each widget's\n * `defaultVisible` (used by the global home to curate a starting set); 'all'\n * shows every eligible widget. Defaults to 'all' on a plugin-home, 'default'\n * on the global home. */\n initialVisibility?: 'default' | 'all'\n /** Route handler for widgets that navigate (defaults to the hash router). */\n onNavigate?: (path: string) => void\n className?: string\n}\n\nexport interface DashboardRangeOptions {\n options?: DashboardRange[]\n default?: DashboardRange\n onChange?: (range: DashboardRange) => void\n}\n\nexport function DashboardCanvas({\n surface, domain, title, subtitle, showHeader = true, appLayout, extraWidgets, range,\n customizable = true, customizeLabel, initialVisibility, onNavigate, className,\n}: DashboardCanvasProps) {\n const runtime = usePluginRuntime()\n const registryWidgets = getDashboardWidgets(runtime, { surface, domain })\n const widgets = React.useMemo<DashboardWidgetDef[]>(() => {\n const extra = (extraWidgets ?? []).filter((w) => {\n if (!(w.surfaces ?? ['home', 'plugin-home']).includes(surface)) return false\n return !domain || w.domain === domain\n })\n return extra.length ? [...registryWidgets, ...extra] : registryWidgets\n }, [registryWidgets, extraWidgets, surface, domain])\n const rangeOpts: DashboardRangeOptions | null = range ? (range === true ? {} : range) : null\n\n const forceAll = (initialVisibility ?? (surface === 'plugin-home' ? 'all' : 'default')) === 'all'\n const { prefs, setVisible, reset } = useDashboardPreferences(surface, domain ?? 'home')\n const laidOut = resolveDashboardLayout(widgets, appLayout, prefs ?? undefined, forceAll)\n const visibleIds = React.useMemo(() => new Set(laidOut.map((w) => w.def.id)), [laidOut])\n\n const hasControls = Boolean(rangeOpts) || (customizable && widgets.length > 0)\n // The shell bar already names this screen — it is a nav entry (\"Painel\"), and\n // printing it again as an <h1> 60px lower was the title twice on the app's\n // first screen. Only where there is no bar (a modal, an embedded canvas) does\n // the dashboard have to say what it is.\n const hasShellBar = useHasPageHeaderHost()\n // Nem título nem descrição quando existe barra: a barra nomeia a tela, e a\n // frase abaixo dela (\"Visão geral da loja\") não diz nada que a grade de\n // cartões logo abaixo não diga melhor — cobra uma linha inteira antes do\n // primeiro número. Sem barra (modal, canvas embutido) o cabeçalho volta.\n const headerBlock = showHeader && !hasShellBar && (title || subtitle) ? (\n <div>\n {title ? <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1> : null}\n {subtitle ? <p className={cn('text-sm text-muted-foreground', title && 'mt-1')}>{subtitle}</p> : null}\n </div>\n ) : null\n\n // Período e \"quais componentes\" são a mesma coisa que a barra de Análises\n // carrega — a pergunta que a tela responde —, então é a MESMA barra: flutuante,\n // à direita, sobre a grade que ela governa. Ver PageToolbar.\n const toolbar = hasControls ? (\n <PageToolbar\n range={rangeOpts ? <DashboardRangeControl /> : null}\n customize={\n customizable && widgets.length > 0 ? (\n <DashboardCustomizeMenu\n widgets={widgets}\n visibleIds={visibleIds}\n onToggle={setVisible}\n onReset={reset}\n label={customizeLabel}\n />\n ) : null\n }\n />\n ) : null\n\n const topRow = (headerBlock || toolbar) ? (\n <>\n {headerBlock}\n {toolbar}\n </>\n ) : null\n\n const content = (\n <div className={className ?? 'space-y-6 p-6'}>\n {topRow}\n\n {widgets.length === 0 ? (\n <Card>\n <CardHeader>\n <CardTitle>Welcome!</CardTitle>\n <CardDescription>Your dashboard will show key metrics and information here.</CardDescription>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-muted-foreground\">\n Enable plugins or register dashboard widgets to populate this view.\n </p>\n </CardContent>\n </Card>\n ) : laidOut.length === 0 ? (\n <Card>\n <CardContent className=\"p-6 text-sm text-muted-foreground\">\n All widgets are hidden. Use “Customize” to choose what to show.\n </CardContent>\n </Card>\n ) : (\n <DashboardGrid items={toGridItems(laidOut)} />\n )}\n </div>\n )\n\n const navWrapped = onNavigate\n ? <DashboardNavigateProvider value={onNavigate}>{content}</DashboardNavigateProvider>\n : content\n\n return rangeOpts\n ? (\n <DashboardRangeProvider options={rangeOpts.options} defaultRange={rangeOpts.default} onChange={rangeOpts.onChange}>\n {navWrapped}\n </DashboardRangeProvider>\n )\n : navWrapped\n}\n","import * as React from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface GoldCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Brand-colored hero variant — `bg-primary text-primary-foreground` with a\n * soft branded shadow. Use for the headline card (e.g. a balance hero). When\n * false (default) it's a plain surface card (`bg-card` + border).\n */\n branded?: boolean\n}\n\n/**\n * GoldCard — a generic, reusable rounded card wrapper for dashboard surfaces.\n *\n * The `branded` variant paints the card in the app's primary color so a single\n * hero (balance, headline KPI, CTA) pops against the neutral grid. Both variants\n * are internally full-width so they reflow cleanly inside the responsive\n * DashboardGrid (full-width on mobile, cell-width on desktop).\n */\nexport const GoldCard = React.forwardRef<HTMLDivElement, GoldCardProps>(\n ({ branded = false, className, children, ...rest }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'h-full rounded-3xl p-5',\n branded\n ? 'bg-primary text-primary-foreground shadow-lg shadow-primary/20'\n : 'border border-border bg-card text-card-foreground shadow-sm',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n ),\n)\nGoldCard.displayName = 'GoldCard'\n","import * as React from 'react'\nimport { getLucideIcon } from '../icons'\nimport type { IconRef } from './types'\n\n/** Resolve an IconRef (lucide name or component) to a renderable element. */\nexport function renderIcon(icon: IconRef | undefined, className = 'h-4 w-4'): React.ReactNode {\n if (!icon) return null\n if (typeof icon === 'string') {\n const Comp = getLucideIcon(icon)\n return Comp ? React.createElement(Comp, { className }) : null\n }\n return React.createElement(icon, { className })\n}\n","import * as React from 'react'\n\n// ---------------------------------------------------------------------------\n// The one sparkline. Dependency-free SVG, oldest → newest, soft area fill.\n//\n// It lived twice — once in KpiCard, once inside the analytics card — and the\n// second copy's comment said \"mirrors the dashboard KpiCard's so tiles read\n// alike\", which is a promise a copy cannot keep. Only the box differs between\n// the two callers, so the box is a prop.\n// ---------------------------------------------------------------------------\n\nexport interface SparklineProps {\n data: number[]\n color: string\n /** viewBox width/height — the aspect the path is drawn into. */\n width?: number\n height?: number\n /** Inset so the stroke is not clipped at the extremes. */\n padding?: number\n className?: string\n}\n\nexport function Sparkline({\n data, color, width = 96, height = 32, padding = 3, className = 'h-8 w-24 shrink-0 overflow-visible',\n}: SparklineProps) {\n const gid = React.useId()\n if (!data || data.length < 2) return null\n\n const min = Math.min(...data)\n const max = Math.max(...data)\n const span = max - min || 1\n const step = (width - padding * 2) / (data.length - 1)\n const pts = data.map((d, i) => [\n padding + i * step,\n padding + (height - padding * 2) * (1 - (d - min) / span),\n ] as const)\n const line = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`).join(' ')\n const area = `${line} L${pts[pts.length - 1]![0].toFixed(1)},${height} L${pts[0]![0].toFixed(1)},${height} Z`\n\n return (\n <svg viewBox={`0 0 ${width} ${height}`} className={className} preserveAspectRatio=\"none\" aria-hidden>\n <defs>\n <linearGradient id={gid} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.22\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={area} fill={`url(#${gid})`} />\n <path\n d={line} fill=\"none\" stroke={color} strokeWidth=\"1.5\"\n strokeLinecap=\"round\" strokeLinejoin=\"round\" vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n )\n}\n","import * as React from 'react'\nimport { TrendingUp, TrendingDown, Minus } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Card, CardContent } from '../primitives/card'\nimport { renderIcon } from './icon'\nimport { Sparkline } from './Sparkline'\nimport type { KpiCurrency, IconRef, KpiFormat, KpiValue, KpiTrend } from './types'\n\nexport function formatKpiValue(value: number, format?: KpiFormat, currency?: KpiCurrency): string {\n const locale = currency?.locale ?? 'pt-BR'\n switch (format) {\n case 'currency':\n return new Intl.NumberFormat(locale, { style: 'currency', currency: currency?.code ?? 'BRL', maximumFractionDigits: 0 }).format(value)\n case 'percent':\n return `${new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }).format(value)}%`\n case 'duration':\n return `${Math.round(value)} min`\n default:\n return new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }).format(value)\n }\n}\n\nfunction deriveTrend(current: number, previous: number | undefined, explicit: KpiTrend | undefined): KpiTrend | undefined {\n if (explicit) return explicit\n if (previous == null) return undefined\n return current > previous ? 'up' : current < previous ? 'down' : 'neutral'\n}\n\nfunction TrendChip({ trend, delta, invert }: { trend: KpiTrend; delta: number | null; invert?: boolean }) {\n if (trend === 'neutral') return null\n const good = invert ? trend === 'down' : trend === 'up'\n const Icon = trend === 'up' ? TrendingUp : TrendingDown\n return (\n <span className={cn(\n 'inline-flex items-center gap-0.5 text-xs font-medium',\n good ? 'text-emerald-600' : 'text-rose-600',\n )}>\n <Icon className=\"h-3 w-3\" />\n {delta != null ? `${delta > 0 ? '+' : ''}${delta}%` : null}\n </span>\n )\n}\n\n/** Trend-aware accent: green when good, red when bad, theme-info when flat. */\nfunction trendColor(trend: KpiTrend | undefined, invert?: boolean): string {\n if (!trend || trend === 'neutral') return 'hsl(var(--info))'\n const good = invert ? trend === 'down' : trend === 'up'\n return good ? '#10b981' : '#f43f5e'\n}\n\n/** Semicircular radial gauge showing `value` as a fraction of `goal`. */\nfunction Gauge({ value, goal, color, children }: { value: number; goal: number; color: string; children: React.ReactNode }) {\n const pct = goal > 0 ? Math.min(1, Math.max(0, value / goal)) : 0\n const R = 40, CX = 50, CY = 46, SW = 9\n const len = Math.PI * R\n const d = `M ${CX - R} ${CY} A ${R} ${R} 0 0 1 ${CX + R} ${CY}`\n return (\n <div className=\"relative mx-auto w-full max-w-[160px]\">\n <svg viewBox=\"0 0 100 52\" className=\"w-full\" aria-hidden>\n <path d={d} fill=\"none\" stroke=\"hsl(var(--muted))\" strokeWidth={SW} strokeLinecap=\"round\" />\n <path\n d={d} fill=\"none\" stroke={color} strokeWidth={SW} strokeLinecap=\"round\"\n strokeDasharray={len} strokeDashoffset={len * (1 - pct)}\n />\n </svg>\n <div className=\"absolute inset-x-0 bottom-0 text-center text-2xl font-semibold tracking-tight text-foreground\">\n {children}\n </div>\n </div>\n )\n}\n\nexport interface KpiCardProps {\n label: string\n icon?: IconRef\n /** Pre-formatted/sync value. Provide this OR `compute`. */\n value?: React.ReactNode\n /** Numeric value formatted via `format`. Ignored when `value` is set. */\n amount?: number\n /** Async loader; the card shows a skeleton until it resolves. */\n compute?: () => Promise<KpiValue>\n format?: KpiFormat\n currency?: KpiCurrency\n sub?: React.ReactNode\n /** Trend chip inputs (for sync usage). */\n current?: number\n previous?: number\n trend?: KpiTrend\n /** For cost-style metrics where down is good (e.g. CPA). */\n invertTrend?: boolean\n /** Inline sparkline series (oldest → newest). Async usage: return via KpiValue.spark. */\n spark?: number[]\n /** Render the card as a radial gauge toward this goal value. */\n goal?: number\n /** Accent color for the sparkline/gauge. Defaults to a trend-aware color. */\n accent?: string\n loading?: boolean\n}\n\n/**\n * Canonical KPI card — consolidates the trend-chip card from plugin-marketing\n * and the async MetricCard from plugin-dashboard. Use directly, or via a\n * registered KPI widget (see defineKpiWidget).\n */\nexport function KpiCard(props: KpiCardProps) {\n const { label, icon, sub, format, currency, invertTrend } = props\n const [computed, setComputed] = React.useState<KpiValue | null>(null)\n const [errored, setErrored] = React.useState(false)\n\n React.useEffect(() => {\n if (!props.compute) return\n let cancelled = false\n props.compute()\n .then((v) => { if (!cancelled) setComputed(v) })\n .catch(() => { if (!cancelled) setErrored(true) })\n return () => { cancelled = true }\n }, [props.compute])\n\n const isAsync = Boolean(props.compute)\n const loading = props.loading || (isAsync && computed === null && !errored)\n\n let display: React.ReactNode = props.value\n let current = props.current\n let previous = props.previous\n let trend = props.trend\n let unit: string | undefined\n let spark = props.spark\n\n if (isAsync && computed) {\n display = formatKpiValue(computed.value, format, currency)\n current = computed.value\n previous = computed.previousValue\n trend = computed.trend\n unit = computed.unit\n spark = computed.spark ?? spark\n } else if (display == null && props.amount != null) {\n display = formatKpiValue(props.amount, format, currency)\n current = current ?? props.amount\n }\n\n const resolvedTrend = current != null ? deriveTrend(current, previous, trend) : trend\n const delta = current != null && previous != null && previous !== 0\n ? Math.round(((current - previous) / previous) * 100)\n : null\n const accent = props.accent ?? trendColor(resolvedTrend, invertTrend)\n\n const valueText = (\n <>\n {display}\n {unit ? <span className=\"ml-1 text-sm font-normal text-muted-foreground\">{unit}</span> : null}\n </>\n )\n const trendChip = resolvedTrend ? <TrendChip trend={resolvedTrend} delta={delta} invert={invertTrend} /> : null\n\n // Pick a body layout: gauge (goal set) → sparkline (series set) → plain.\n const isGauge = props.goal != null && current != null\n const hasSpark = Boolean(spark && spark.length >= 2)\n\n let body: React.ReactNode\n if (errored) {\n body = <span className=\"text-sm text-muted-foreground\">—</span>\n } else if (loading) {\n body = isGauge\n ? <div className=\"mx-auto h-16 w-32 animate-pulse rounded bg-muted\" />\n : <div className=\"h-7 w-20 animate-pulse rounded bg-muted\" />\n } else if (isGauge) {\n body = (\n <div>\n <Gauge value={current!} goal={props.goal!} color={accent}>{valueText}</Gauge>\n <div className=\"mt-1 flex items-center justify-center gap-2 text-xs text-muted-foreground\">\n {trendChip}\n <span>{sub ?? `out of ${formatKpiValue(props.goal!, format, currency)}`}</span>\n </div>\n </div>\n )\n } else if (hasSpark) {\n body = (\n <div className=\"flex items-end justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"text-2xl font-semibold tracking-tight text-foreground\">{valueText}</div>\n {trendChip ? <div className=\"mt-0.5\">{trendChip}</div> : null}\n </div>\n <Sparkline data={spark!} color={accent} />\n </div>\n )\n } else {\n body = (\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-2xl font-semibold tracking-tight text-foreground\">{valueText}</span>\n {trendChip ? <span className=\"mb-0.5\">{trendChip}</span> : null}\n </div>\n )\n }\n\n return (\n // h-full so cards fill the (stretch) grid cell and every card in a row matches\n // the tallest — labels/subtitles of different lengths no longer misalign them.\n <Card className=\"h-full\">\n <CardContent className=\"flex h-full flex-col p-4\">\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <span className=\"text-sm text-muted-foreground\">{label}</span>\n <span className=\"text-muted-foreground\">{renderIcon(icon)}</span>\n </div>\n {body}\n {sub && !isGauge ? <p className=\"mt-0.5 text-xs text-muted-foreground\">{sub}</p> : null}\n </CardContent>\n </Card>\n )\n}\n","import * as React from 'react'\nimport { Card, CardContent, CardHeader, CardTitle } from '../primitives/card'\nimport { renderIcon } from './icon'\nimport type { ChartSeries, ChartType, IconRef } from './types'\n\nexport interface ChartWidgetProps {\n type: ChartType\n /** Rows of data; each key referenced by a series.dataKey. */\n data: Array<Record<string, string | number>>\n series: ChartSeries[]\n /** Key for the category axis (x-axis / pie label). */\n categoryKey?: string\n title?: string\n icon?: IconRef\n /** Right-aligned header content (e.g. a range selector). */\n headerAction?: React.ReactNode\n height?: number\n className?: string\n}\n\n// The recharts body is lazy so recharts ships as an async chunk instead of in\n// every consumer's entry bundle; the Card shell renders immediately and the\n// fallback reserves the chart's height to avoid layout shift.\nconst ChartWidgetInner = React.lazy(() => import('./ChartWidgetInner'))\n\n/**\n * One chart failing must cost one chart.\n *\n * A lazy body has two ways to fail — the chunk never arrives, or recharts\n * throws on the data — and with no boundary either one unmounts the whole page\n * up to the app root, so a page of twenty cards goes blank because one of them\n * had a bad row. It also swallowed the *reason*: the console showed a component\n * stack ending at `Lazy` and nothing about what actually broke. This prints it\n * where the chart was.\n */\nclass ChartBoundary extends React.Component<\n { height: number; children: React.ReactNode },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null }\n\n static getDerivedStateFromError(error: Error) {\n return { error }\n }\n\n render() {\n if (!this.state.error) return this.props.children\n return (\n <div\n className=\"flex items-center justify-center px-3 text-center text-xs text-muted-foreground\"\n style={{ height: this.props.height }}\n >\n {this.state.error.message || 'Chart failed to render'}\n </div>\n )\n }\n}\n\n/** recharts-backed chart in a Card. Replaces the hand-rolled CSS bar charts. */\nexport function ChartWidget({\n type, data, series, categoryKey = 'name', title, icon, headerAction, height = 240, className,\n}: ChartWidgetProps) {\n return (\n <Card className={className}>\n {(title || headerAction) && (\n <CardHeader className=\"flex-row items-center justify-between space-y-0\">\n {title ? (\n <CardTitle className=\"flex items-center gap-2\">\n {renderIcon(icon)}\n {title}\n </CardTitle>\n ) : <span />}\n {headerAction}\n </CardHeader>\n )}\n <CardContent className=\"p-4 pt-2\">\n <ChartBoundary height={height}>\n <React.Suspense fallback={<div style={{ height }} />}>\n <ChartWidgetInner type={type} data={data} series={series} categoryKey={categoryKey} height={height} />\n </React.Suspense>\n </ChartBoundary>\n </CardContent>\n </Card>\n )\n}\n","import * as React from 'react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Card, CardContent, CardHeader, CardTitle } from '../primitives/card'\nimport { DataTable } from '../primitives/data-table'\nimport { renderIcon } from './icon'\nimport type { IconRef } from './types'\n\nexport interface TableWidgetProps<TData> {\n title?: string\n icon?: IconRef\n columns: ColumnDef<TData, unknown>[]\n data: TData[]\n loading?: boolean\n emptyMessage?: string\n onRowClick?: (row: TData) => void\n /** Right-aligned header content (e.g. a \"view all\" link). */\n headerAction?: React.ReactNode\n className?: string\n}\n\n/** \"Recent N\" table in a Card — wraps the shared DataTable primitive. */\nexport function TableWidget<TData>({\n title, icon, columns, data, loading, emptyMessage, onRowClick, headerAction, className,\n}: TableWidgetProps<TData>) {\n return (\n <Card className={className}>\n {(title || headerAction) && (\n <CardHeader className=\"flex-row items-center justify-between space-y-0\">\n {title ? (\n <CardTitle className=\"flex items-center gap-2\">\n {renderIcon(icon)}\n {title}\n </CardTitle>\n ) : <span />}\n {headerAction}\n </CardHeader>\n )}\n <CardContent className=\"p-0\">\n <DataTable\n columns={columns}\n data={data}\n loading={loading}\n emptyMessage={emptyMessage}\n onRowClick={onRowClick}\n variant=\"flat\"\n compact\n />\n </CardContent>\n </Card>\n )\n}\n","import * as React from 'react'\nimport type { OnboardingStepInput } from './types'\n\nexport interface OnboardingProgress {\n /** Per-step completion, keyed by step id. */\n completed: Record<string, boolean>\n /** False until every async `check` has settled — render a skeleton until then. */\n resolved: boolean\n doneCount: number\n total: number\n allDone: boolean\n /** First step still pending — the one a compact UI should offer to start. */\n nextStep: OnboardingStepInput | undefined\n /** Run a step's `action`, routing string actions through `onNavigate`. */\n run: (action: OnboardingStepInput['action']) => void\n}\n\n/**\n * The onboarding checklist's whole behaviour, minus the rendering: resolve each\n * step's async `check`, hold back the paint until they all settle, and count.\n *\n * Extracted so the dashboard card (OnboardingWidget) and the sidebar card\n * (SidebarOnboarding) are two skins over ONE source of truth — otherwise the\n * two would drift, and a store could plausibly read \"2 of 5\" in the sidebar\n * while the dashboard said 3.\n *\n * `steps` is the effect's dependency by identity, so callers must build the\n * array once (module scope or useMemo) rather than inline per render.\n */\nexport function useOnboardingProgress(\n steps: OnboardingStepInput[],\n onNavigate?: (path: string) => void,\n): OnboardingProgress {\n const [completed, setCompleted] = React.useState<Record<string, boolean>>(() =>\n Object.fromEntries(steps.map((s) => [s.id, Boolean(s.done)])),\n )\n // Async checks start unresolved: don't paint until they settle, or an\n // already-onboarded tenant flashes the checklist for the query round-trip.\n const [resolved, setResolved] = React.useState(() => steps.every((s) => s.done != null || !s.check))\n\n React.useEffect(() => {\n let cancelled = false\n Promise.all(steps.map(async (s) => {\n if (s.done != null) return [s.id, s.done] as const\n if (!s.check) return [s.id, false] as const\n try { return [s.id, await s.check()] as const } catch { return [s.id, false] as const }\n })).then((entries) => {\n if (cancelled) return\n setCompleted(Object.fromEntries(entries))\n setResolved(true)\n })\n return () => { cancelled = true }\n }, [steps])\n\n const doneCount = steps.filter((s) => completed[s.id]).length\n\n const run = React.useCallback((action: OnboardingStepInput['action']) => {\n if (!action) return\n if (typeof action === 'string') onNavigate?.(action)\n else action()\n }, [onNavigate])\n\n return {\n completed,\n resolved,\n doneCount,\n total: steps.length,\n allDone: doneCount === steps.length,\n nextStep: steps.find((s) => !completed[s.id]),\n run,\n }\n}\n","import * as React from 'react'\nimport { Check, Circle } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Card, CardContent, CardHeader, CardTitle, CardDescription } from '../primitives/card'\nimport { Button } from '../primitives/button'\nimport { Skeleton } from '../primitives/skeleton'\nimport { renderIcon } from './icon'\nimport { useOnboardingProgress } from './useOnboardingProgress'\nimport type { OnboardingStepInput } from './types'\n\nexport type { OnboardingStepInput }\n\nexport interface OnboardingWidgetProps {\n title?: string\n subtitle?: string\n steps: OnboardingStepInput[]\n onNavigate?: (path: string) => void\n /** Hide the whole widget once every step is complete. Default: true. */\n hideWhenComplete?: boolean\n className?: string\n}\n\n/** Placeholder mirroring the widget's layout while the async checks resolve. */\nfunction OnboardingSkeleton({ rows, className }: { rows: number; className?: string }) {\n return (\n <Card className={className} aria-busy=\"true\">\n <CardHeader>\n <Skeleton className=\"h-5 w-40\" />\n <Skeleton className=\"mt-1.5 h-3.5 w-64 max-w-full\" />\n <div className=\"mt-2 flex items-center gap-3\">\n <Skeleton className=\"h-1.5 flex-1 rounded-full\" />\n <Skeleton className=\"h-3 w-8\" />\n </div>\n </CardHeader>\n <CardContent className=\"space-y-1 pt-0\">\n {Array.from({ length: Math.max(rows, 1) }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-2 py-2.5\">\n <Skeleton className=\"h-7 w-7 shrink-0 rounded-full\" />\n <div className=\"min-w-0 flex-1 space-y-1.5\">\n <Skeleton className=\"h-3.5 w-1/2\" />\n <Skeleton className=\"h-3 w-3/4\" />\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n )\n}\n\n/** Getting-started checklist (\"first steps to set up\") with progress. */\nexport function OnboardingWidget({\n title = 'Getting started', subtitle, steps, onNavigate, hideWhenComplete = true, className,\n}: OnboardingWidgetProps) {\n const { completed, resolved, doneCount, allDone, run: runAction } = useOnboardingProgress(steps, onNavigate)\n\n // Hold the card's real shape while the checks settle. Painting the resolved\n // checklist here would flash 0/N at an already-onboarded tenant, and painting\n // nothing collapsed the row and shifted the dashboard on resolve.\n if (!resolved) return <OnboardingSkeleton rows={steps.length} className={className} />\n if (allDone && hideWhenComplete) return null\n\n return (\n <Card className={className}>\n <CardHeader>\n <CardTitle>{title}</CardTitle>\n {subtitle ? <CardDescription>{subtitle}</CardDescription> : null}\n <div className=\"mt-2 flex items-center gap-3\">\n <div className=\"h-1.5 flex-1 overflow-hidden rounded-full bg-muted\">\n <div className=\"h-full rounded-full bg-primary transition-all\"\n style={{ width: `${steps.length ? (doneCount / steps.length) * 100 : 0}%` }} />\n </div>\n <span className=\"text-xs font-medium text-muted-foreground\">{doneCount}/{steps.length}</span>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-1 pt-0\">\n {steps.map((step) => {\n const isDone = completed[step.id]\n return (\n <div key={step.id} className=\"flex items-center gap-3 rounded-lg px-2 py-2.5 hover:bg-muted/50\">\n <span className={cn(\n 'flex h-7 w-7 shrink-0 items-center justify-center rounded-full',\n isDone ? 'bg-emerald-100 text-emerald-600' : 'bg-muted text-muted-foreground',\n )}>\n {isDone ? <Check className=\"h-4 w-4\" /> : (renderIcon(step.icon, 'h-4 w-4') ?? <Circle className=\"h-4 w-4\" />)}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className={cn('text-sm font-medium', isDone && 'text-muted-foreground line-through')}>{step.title}</p>\n {step.description ? <p className=\"truncate text-xs text-muted-foreground\">{step.description}</p> : null}\n </div>\n {!isDone && step.action ? (\n <Button size=\"sm\" variant=\"outline\" onClick={() => runAction(step.action)}>\n {step.actionLabel ?? 'Start'}\n </Button>\n ) : null}\n </div>\n )\n })}\n </CardContent>\n </Card>\n )\n}\n","import * as React from 'react'\nimport { ArrowRight, Check, Circle } from 'lucide-react'\nimport { cn } from '../lib/cn'\nimport { Skeleton } from '../primitives/skeleton'\nimport { useLayoutStore } from '../stores/layout.store'\nimport { useOnboardingProgress } from './useOnboardingProgress'\nimport type { OnboardingStepInput } from './types'\n\nexport interface SidebarOnboardingProps {\n title?: string\n steps: OnboardingStepInput[]\n onNavigate?: (path: string) => void\n /** Hide the whole card once every step is complete. Default: true. */\n hideWhenComplete?: boolean\n /**\n * @deprecated The checklist no longer folds inline — it is always one line in\n * the rail and opens its steps in a panel on hover, so there is no collapsed\n * state left to remember. Still accepted so existing hosts keep compiling.\n */\n storageKey?: string\n className?: string\n}\n\nconst COUNT_LABEL = (done: number, total: number) => `${done} de ${total}`\n\n/** Ring geometry for the collapsed rail's badge. */\nconst RING_SIZE = 30\nconst RING_RADIUS = 12\nconst RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS\n\n/**\n * The getting-started checklist as it fits a sidebar — a single line, not a\n * card.\n *\n * It used to print every step inline, which cost the rail a third of its height\n * to say things the user reads once; and it was painted in the PAGE's tones, so\n * a white card sat in the middle of a dark menu (and in a 4rem rail it was a\n * white block with \"4 de 5\" floating in it). Now the rail carries the progress\n * only — a count and a hairline expanded, a ring collapsed — and the steps come\n * out to the right on hover, in the menu's own colours.\n *\n * Same steps and same resolution logic as the dashboard's OnboardingWidget\n * (both run useOnboardingProgress); deliberately NOT a variant prop on it —\n * they share behaviour, not layout.\n */\nexport function SidebarOnboarding({\n title = 'Primeiros passos',\n steps,\n onNavigate,\n hideWhenComplete = true,\n className,\n}: SidebarOnboardingProps) {\n const { completed, resolved, doneCount, allDone, nextStep, run } = useOnboardingProgress(steps, onNavigate)\n const railCollapsed = useLayoutStore((s) => s.sidebarCollapsed)\n const [open, setOpen] = React.useState(false)\n const closeTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const cancelClose = () => {\n if (closeTimer.current) {\n clearTimeout(closeTimer.current)\n closeTimer.current = null\n }\n }\n const show = () => {\n cancelClose()\n setOpen(true)\n }\n // A small delay so crossing the gap between the row and the panel doesn't\n // close what you are reaching for.\n const hide = () => {\n cancelClose()\n closeTimer.current = setTimeout(() => setOpen(false), 140)\n }\n React.useEffect(() => () => cancelClose(), [])\n\n if (!resolved) {\n return railCollapsed ? (\n <div className=\"flex justify-center py-1\" aria-busy=\"true\">\n <Skeleton className=\"h-8 w-8 rounded-full bg-sidebar-accent\" />\n </div>\n ) : (\n <div className={cn('px-1 py-1.5', className)} aria-busy=\"true\">\n <Skeleton className=\"h-3 w-24 bg-sidebar-accent\" />\n <Skeleton className=\"mt-2 h-1 w-full rounded-full bg-sidebar-accent\" />\n </div>\n )\n }\n if (allDone && hideWhenComplete) return null\n\n const pct = steps.length ? (doneCount / steps.length) * 100 : 0\n\n const trigger = railCollapsed ? (\n <button\n type=\"button\"\n onClick={() => (open ? hide() : show())}\n title={`${title} — ${COUNT_LABEL(doneCount, steps.length)}`}\n aria-label={`${title} — ${COUNT_LABEL(doneCount, steps.length)}`}\n className=\"flex w-full items-center justify-center rounded-button p-1 text-sidebar-foreground/80 transition-colors hover:bg-sidebar-accent/60\"\n >\n <span className=\"relative flex items-center justify-center\">\n <svg width={RING_SIZE} height={RING_SIZE} viewBox={`0 0 ${RING_SIZE} ${RING_SIZE}`} className=\"-rotate-90\">\n <circle\n cx={RING_SIZE / 2} cy={RING_SIZE / 2} r={RING_RADIUS}\n fill=\"none\" strokeWidth=\"2.5\"\n className=\"stroke-sidebar-border\"\n />\n <circle\n cx={RING_SIZE / 2} cy={RING_SIZE / 2} r={RING_RADIUS}\n fill=\"none\" strokeWidth=\"2.5\" strokeLinecap=\"round\"\n strokeDasharray={RING_CIRCUMFERENCE}\n strokeDashoffset={RING_CIRCUMFERENCE * (1 - pct / 100)}\n className=\"stroke-current text-sidebar-foreground transition-[stroke-dashoffset] duration-300\"\n />\n </svg>\n <span className=\"absolute text-[9px] font-semibold tabular-nums text-sidebar-foreground\">\n {doneCount}/{steps.length}\n </span>\n </span>\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => (open ? hide() : show())}\n aria-expanded={open}\n className={cn(\n 'w-full rounded-button px-1.5 py-1.5 text-left transition-colors hover:bg-sidebar-accent/50',\n className,\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 truncate text-[12px] font-medium text-sidebar-foreground/90\">{title}</span>\n <span className=\"shrink-0 text-[11px] tabular-nums text-sidebar-muted\">\n {COUNT_LABEL(doneCount, steps.length)}\n </span>\n </span>\n <span className=\"mt-1.5 block h-1 overflow-hidden rounded-full bg-sidebar-accent\">\n <span\n className=\"block h-full rounded-full bg-sidebar-foreground/70 transition-all\"\n style={{ width: `${pct}%` }}\n />\n </span>\n </button>\n )\n\n return (\n <div className=\"relative\" onMouseEnter={show} onMouseLeave={hide}>\n {trigger}\n <div\n onMouseEnter={cancelClose}\n onMouseLeave={hide}\n aria-hidden={!open}\n className={cn(\n 'absolute bottom-0 left-full z-50 ml-2 hidden w-64 md:block',\n 'motion-safe:transition-opacity motion-safe:duration-150',\n open ? 'opacity-100' : 'pointer-events-none opacity-0',\n )}\n >\n {/* Menu tones, like every other panel that leans out of the rail. */}\n <div className=\"rounded-lg border border-sidebar-border bg-sidebar p-2 text-sidebar-foreground shadow-xl shadow-black/25\">\n <div className=\"flex items-center gap-2 px-1 pb-1.5\">\n <span className=\"min-w-0 flex-1 truncate text-[12.5px] font-semibold\">{title}</span>\n <span className=\"shrink-0 text-[11px] tabular-nums text-sidebar-muted\">\n {COUNT_LABEL(doneCount, steps.length)}\n </span>\n </div>\n <div className=\"mx-1 h-1 overflow-hidden rounded-full bg-sidebar-accent\">\n <div className=\"h-full rounded-full bg-sidebar-foreground/70 transition-all\" style={{ width: `${pct}%` }} />\n </div>\n <ul className=\"mt-1.5 space-y-0.5\">\n {steps.map((step) => {\n const isDone = completed[step.id]\n // Only the first pending step offers its action. Five simultaneous\n // \"Start\" buttons is noise, and the checklist is ordered — the next\n // thing to do is the next thing to do.\n const isNext = !isDone && step.id === nextStep?.id\n return (\n <li key={step.id}>\n <button\n type=\"button\"\n disabled={isDone || !step.action}\n onClick={() => {\n setOpen(false)\n run(step.action)\n }}\n className={cn(\n 'group flex w-full items-center gap-2 rounded-md px-1.5 py-1.5 text-left transition-colors',\n !isDone && step.action && 'hover:bg-sidebar-accent/60',\n isDone && 'cursor-default',\n )}\n >\n {isDone\n ? <Check className=\"h-3.5 w-3.5 shrink-0 rounded-full bg-sidebar-accent p-[1px] text-sidebar-muted\" />\n : <Circle className=\"h-3.5 w-3.5 shrink-0 text-sidebar-muted\" />}\n <span className={cn(\n 'min-w-0 flex-1 text-[12.5px] leading-snug',\n isDone ? 'text-sidebar-muted line-through' : 'text-sidebar-foreground',\n )}>\n {step.title}\n </span>\n {isNext && step.action && (\n <span\n aria-hidden\n className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-sidebar-border text-sidebar-muted opacity-0 transition-opacity group-hover:opacity-100\"\n >\n <ArrowRight className=\"h-3 w-3\" />\n </span>\n )}\n </button>\n </li>\n )\n })}\n </ul>\n </div>\n </div>\n </div>\n )\n}\n","import type { DashboardWidgetDef, DashboardWidgetKind, DashboardSurface } from '@fayz-ai/core'\n\n// ---------------------------------------------------------------------------\n// Widget-definition builders. Each sets the right `kind` + default `span` so a\n// plugin author writes data, not layout. The widget's component renders the\n// presentational primitives (KpiCard, ChartWidget, TableWidget, ...).\n// ---------------------------------------------------------------------------\n\nexport interface DefineWidgetInput {\n id: string\n title: string\n component: React.ComponentType<unknown>\n description?: string\n icon?: string\n domain?: string\n span?: 1 | 2 | 3 | 4\n defaultVisible?: boolean\n defaultOrder?: number\n surfaces?: DashboardSurface[]\n verticalId?: DashboardWidgetDef['verticalId']\n permission?: DashboardWidgetDef['permission']\n props?: Record<string, unknown>\n}\n\nfunction build(kind: DashboardWidgetKind, defaultSpan: 1 | 2 | 3 | 4, input: DefineWidgetInput): DashboardWidgetDef {\n return {\n kind,\n span: input.span ?? defaultSpan,\n defaultVisible: input.defaultVisible ?? true,\n id: input.id,\n title: input.title,\n description: input.description,\n icon: input.icon,\n domain: input.domain,\n defaultOrder: input.defaultOrder,\n surfaces: input.surfaces,\n verticalId: input.verticalId,\n permission: input.permission,\n component: input.component,\n props: input.props,\n }\n}\n\n/** KPI card widget — spans 1 column (forms the 4-up top row). */\nexport const defineKpiWidget = (input: DefineWidgetInput): DashboardWidgetDef => build('kpi', 1, input)\n/** Chart widget — spans 2 columns by default. */\nexport const defineChartWidget = (input: DefineWidgetInput): DashboardWidgetDef => build('chart', 2, input)\n/** Table widget — spans the full row by default. */\nexport const defineTableWidget = (input: DefineWidgetInput): DashboardWidgetDef => build('table', 4, input)\n/** Onboarding checklist widget — spans half the row (2 cols) by default. */\nexport const defineOnboardingWidget = (input: DefineWidgetInput): DashboardWidgetDef => build('onboarding', 2, input)\n/** Custom client-provided widget — spans 2 columns by default. */\nexport const defineCustomWidget = (input: DefineWidgetInput): DashboardWidgetDef => build('custom', 2, input)\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stores/page-header.store.ts","../src/stores/layout.store.ts"],"names":["create"],"mappings":"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","file":"chunk-FFJ2C5YH.js","sourcesContent":["import * as React from 'react'\nimport { create } from 'zustand'\n\ninterface PageHeaderState {\n /** What the shell's top bar shows INSTEAD of the page title, or null. */\n slot: React.ReactNode | null\n /** Identity of whoever owns the slot, so a late unmount can't clear a newer\n * owner's content — the exact race you get navigating form → form. */\n owner: string | null\n /** The claimed header carries a back action, i.e. what the bar is showing is\n * a SUBPAGE (\"← Contas a Pagar / Nova\"), not the module's own screen. The\n * module's tab band reads this to step aside: a form reached from a tab is\n * not one of the tabs, and leaving the strip up marks a place the user is no\n * longer at, one line under a back link that says so. */\n hasBack: boolean\n /** How many shells are currently rendering the slot. A page needs to know:\n * with no host (minimal layout, an embedded form, a modal) its header would\n * be claimed into the void, and the page must draw it inline instead. */\n hosts: number\n /**\n * Quantos OUTLETS internos estão mostrando o slot. Um outlet é um container\n * mais fundo que a shell — a coluna de conteúdo de um módulo com trilha\n * lateral — que fica em melhor posição para desenhar o cabeçalho.\n *\n * Quando existe um, a barra da shell se cala: as duas juntas desenhariam a\n * mesma migalha duas vezes, e a da shell atravessa a largura inteira,\n * empurrando a trilha do módulo para baixo do topo.\n */\n outlets: number\n /**\n * Quantos blocos de ações de página estão montados agora. A barra precisa\n * saber ANTES de decidir se existe: ela some no celular de alguns produtos, e\n * um \"Novo\" entregue a uma barra escondida simplesmente não aparecia.\n */\n actions: number\n claim: (owner: string, node: React.ReactNode, hasBack?: boolean) => void\n release: (owner: string) => void\n addHost: () => void\n removeHost: () => void\n addOutlet: () => void\n removeOutlet: () => void\n addActions: () => void\n removeActions: () => void\n}\n\nconst usePageHeaderStore = create<PageHeaderState>((set, get) => ({\n slot: null,\n owner: null,\n hasBack: false,\n hosts: 0,\n outlets: 0,\n actions: 0,\n claim: (owner, node, hasBack = false) => set({ owner, slot: node, hasBack }),\n release: (owner) => {\n if (get().owner === owner) set({ owner: null, slot: null, hasBack: false })\n },\n addHost: () => set((s) => ({ hosts: s.hosts + 1 })),\n removeHost: () => set((s) => ({ hosts: Math.max(0, s.hosts - 1) })),\n addOutlet: () => set((s) => ({ outlets: s.outlets + 1 })),\n removeOutlet: () => set((s) => ({ outlets: Math.max(0, s.outlets - 1) })),\n addActions: () => set((s) => ({ actions: s.actions + 1 })),\n removeActions: () => set((s) => ({ actions: Math.max(0, s.actions - 1) })),\n}))\n\n/** Declara que esta página tem ações no topo. Chamado por PageHeaderActions. */\nexport function useRegisterPageActions(): void {\n const add = usePageHeaderStore((s) => s.addActions)\n const remove = usePageHeaderStore((s) => s.removeActions)\n React.useEffect(() => {\n add()\n return remove\n }, [add, remove])\n}\n\n/** Se alguma página tem ações no topo agora. A barra usa para não sumir com\n * elas no celular, e para não existir vazia. */\nexport function useHasPageActions(): boolean {\n return usePageHeaderStore((s) => s.actions > 0)\n}\n\n/** Read the current override. The shell calls this; pages should not. */\nexport function usePageHeaderSlot(): React.ReactNode | null {\n return usePageHeaderStore((s) => s.slot)\n}\n\n/**\n * Declare that this shell renders the page-header slot. Called by the layout,\n * never by a page. Without it `PageHeader` cannot tell \"nobody claimed the bar\"\n * from \"there is no bar\", and a header would vanish instead of falling back.\n */\nexport function usePageHeaderHost(): void {\n const addHost = usePageHeaderStore((s) => s.addHost)\n const removeHost = usePageHeaderStore((s) => s.removeHost)\n React.useEffect(() => {\n addHost()\n return removeHost\n }, [addHost, removeHost])\n}\n\n/** Whether any shell OR inner outlet is showing the slot right now. */\nexport function useHasPageHeaderHost(): boolean {\n return usePageHeaderStore((s) => s.hosts > 0 || s.outlets > 0)\n}\n\n/** True when a deeper container took over drawing the header. The shell bar\n * uses this to stand down. */\nexport function useHasPageHeaderOutlet(): boolean {\n return usePageHeaderStore((s) => s.outlets > 0)\n}\n\n/**\n * Desenha o cabeçalho AQUI em vez de na barra da shell.\n *\n * Para quem tem uma coluna própria de conteúdo — um módulo com trilha lateral —,\n * onde a barra da shell, larga demais, passaria por cima da trilha.\n */\nexport function PageHeaderOutlet({ className }: { className?: string }): React.ReactElement | null {\n const slot = usePageHeaderStore((s) => s.slot)\n const addOutlet = usePageHeaderStore((s) => s.addOutlet)\n const removeOutlet = usePageHeaderStore((s) => s.removeOutlet)\n\n React.useEffect(() => {\n addOutlet()\n return removeOutlet\n }, [addOutlet, removeOutlet])\n\n if (!slot) return null\n return React.createElement('div', { className: className ?? 'mb-4' }, slot)\n}\n\n/**\n * Put this page's own header — a back link, a breadcrumb — into the shell's top\n * bar, replacing the page title for as long as the page is mounted.\n *\n * Prefer the `PageHeader` component: it is this hook plus the one agreed layout\n * (← + title), so every screen in every app reads the same. Reach for the hook\n * directly only for a header that genuinely is not \"back + title\".\n *\n * A form or detail screen already says where it is (\"← Novo produto\") and the\n * bar above it was saying \"Produtos\" again, one line up. Two headers stacked is\n * a whole row of vertical space spent repeating a word.\n *\n * The node is re-claimed on every change so a breadcrumb whose label depends on\n * loaded data (a record's name) updates once it arrives.\n */\nexport function usePageHeader(node: React.ReactNode | null, options?: { back?: boolean }): void {\n const id = React.useId()\n const claim = usePageHeaderStore((s) => s.claim)\n const release = usePageHeaderStore((s) => s.release)\n const back = options?.back ?? false\n\n React.useEffect(() => {\n if (node == null) {\n release(id)\n return\n }\n claim(id, node, back)\n return () => release(id)\n }, [id, node, back, claim, release])\n}\n\n/** True while the bar is showing a subpage's \"← parent / title\". See\n * `PageHeaderState.hasBack`. */\nexport function useHasPageHeaderBack(): boolean {\n return usePageHeaderStore((s) => s.hasBack)\n}\n\nexport { usePageHeaderStore }\n","import { create } from 'zustand'\n\ninterface LayoutState {\n sidebarOpen: boolean\n sidebarCollapsed: boolean\n mobileDrawerOpen: boolean\n commandPaletteOpen: boolean\n toggleSidebar: () => void\n setSidebarCollapsed: (collapsed: boolean) => void\n toggleMobileDrawer: () => void\n setCommandPaletteOpen: (open: boolean) => void\n}\n\nexport const useLayoutStore = create<LayoutState>((set) => ({\n sidebarOpen: true,\n sidebarCollapsed: false,\n mobileDrawerOpen: false,\n commandPaletteOpen: false,\n\n toggleSidebar: () =>\n set((state) => ({ sidebarOpen: !state.sidebarOpen })),\n\n setSidebarCollapsed: (collapsed) =>\n set({ sidebarCollapsed: collapsed }),\n\n toggleMobileDrawer: () =>\n set((state) => ({ mobileDrawerOpen: !state.mobileDrawerOpen })),\n\n setCommandPaletteOpen: (open) =>\n set({ commandPaletteOpen: open }),\n}))\n"]}
|