forlogic-core 2.0.4 → 2.0.5
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/.note/memory/features/crud-defaults-batteries-included.md +1 -1
- package/dist/components/ui/dialog-wizard.d.ts +82 -0
- package/dist/components/ui/input-group.d.ts +1 -1
- package/dist/components/ui/input.d.ts +5 -23
- package/dist/components/ui/resizable.d.ts +1 -1
- package/dist/components/ui/sidebar.d.ts +1 -1
- package/dist/components/ui/step-selector.d.ts +11 -9
- package/dist/components/ui/textarea.d.ts +1 -0
- package/dist/crud/components/CrudTable.d.ts +3 -1
- package/dist/crud/createCrudPage.d.ts +2 -0
- package/dist/crud/hooks/useColumnManager.d.ts +3 -1
- package/dist/exports/ui.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/types.d.ts +3 -0
- package/docs/design-system/README.md +2 -2
- package/docs/design-system/buttons-actions.md +6 -0
- package/docs/design-system/domain.md +10 -0
- package/docs/design-system/inputs.md +20 -0
- package/docs/design-system/navigation.md +5 -0
- package/docs/design-system/notifications-feedback.md +2 -0
- package/package.json +1 -1
- package/dist/assets/AccordionDoc-CGNlubG3.js +0 -31
- package/dist/assets/ActionButtonDoc-CYtkXR0k.js +0 -47
- package/dist/assets/ActionPlanDoc-BSuPRftQ.js +0 -65
- package/dist/assets/AlertDoc-Cpvxneqg.js +0 -37
- package/dist/assets/AliasUrlDoc-DIpUWf4Y.js +0 -189
- package/dist/assets/AppHeaderDoc-DNQErj_t.js +0 -74
- package/dist/assets/AppSidebarDoc-DkeQarDu.js +0 -221
- package/dist/assets/ApprovalFlowDoc-8YgXbhKJ.js +0 -31
- package/dist/assets/AuditLogDoc-BBvNcHIo.js +0 -67
- package/dist/assets/AuditTrailDoc-DgFHO-uo.js +0 -17
- package/dist/assets/AuthDoc-WIA_Aetl.js +0 -200
- package/dist/assets/AvatarDoc-B6go1C1T.js +0 -11
- package/dist/assets/BadgeDoc-BONhfqB_.js +0 -36
- package/dist/assets/BaseFormDoc-CuyUArcj.js +0 -169
- package/dist/assets/BodyContentDoc-CterHC1E.js +0 -83
- package/dist/assets/BreadcrumbDoc-Dwn9nLeO.js +0 -75
- package/dist/assets/ButtonDoc-BOjRseZT.js +0 -41
- package/dist/assets/ButtonGroupDoc-8IS6PPh4.js +0 -7
- package/dist/assets/CalendarDoc-CMwIEqgT.js +0 -81
- package/dist/assets/CardDoc-BZz1CVg2.js +0 -49
- package/dist/assets/ChartDoc-B5vZVtqD.js +0 -76
- package/dist/assets/CheckboxDoc-lAbYO9I5.js +0 -55
- package/dist/assets/ColorPickerDoc-Dpsprp4N.js +0 -10
- package/dist/assets/ColorsFoundationDoc-CCHeSL3p.js +0 -13
- package/dist/assets/ComboTreeDoc-D4dTkIt-.js +0 -46
- package/dist/assets/ComboboxDoc-CqqZPvZq.js +0 -134
- package/dist/assets/ComponentDocTemplate-CQbBhfvZ.js +0 -1
- package/dist/assets/ContextMenuDoc-D3jC-MVA.js +0 -182
- package/dist/assets/ContextsDoc-XFH0-JdS.js +0 -211
- package/dist/assets/CreateCrudPageDoc-CpuiWI-g.js +0 -106
- package/dist/assets/CrudActionBarDoc-wuBGXD9Y.js +0 -112
- package/dist/assets/CrudGridDoc-BYWqSXBH.js +0 -85
- package/dist/assets/CrudOverviewDoc-B_bk2a2t.js +0 -14
- package/dist/assets/CrudPrimitivesDoc-CxaTB94A.js +0 -164
- package/dist/assets/CrudTableDoc-Dga1VgCu.js +0 -113
- package/dist/assets/CustomFormFieldsDoc-C1hwwSl3.js +0 -33
- package/dist/assets/DashboardFormDoc-BUDCmrMl.js +0 -49
- package/dist/assets/DashboardGeneralViewDoc-Cyg1SIiG.js +0 -71
- package/dist/assets/DashboardGridDoc-BavePiRF.js +0 -49
- package/dist/assets/DashboardListDoc-CLyMA6UK.js +0 -37
- package/dist/assets/DashboardOverviewDoc-DRVvNIF1.js +0 -35
- package/dist/assets/DashboardPanelRendererDoc--mfwb8Nc.js +0 -60
- package/dist/assets/DashboardPanelsBasicDoc-BQ2V_52D.js +0 -62
- package/dist/assets/DashboardPanelsCartesianDoc-sy-hcVQY.js +0 -75
- package/dist/assets/DashboardPanelsSpecialDoc-DsIUCRRP.js +0 -83
- package/dist/assets/DashboardViewDoc-CtlCNlEF.js +0 -45
- package/dist/assets/DataListDoc-DUy88lCQ.js +0 -13
- package/dist/assets/DesignSystemHome-DHl9YtbH.js +0 -1
- package/dist/assets/DialogDoc-CMQqnTV-.js +0 -981
- package/dist/assets/DropdownMenuDoc-S7X9csGt.js +0 -175
- package/dist/assets/ElectronicSignatureDialogDoc-BfithaL_.js +0 -57
- package/dist/assets/EmptyStateDoc-CHGCiGIk.js +0 -35
- package/dist/assets/EnvironmentsDoc-DZHJZ2nm.js +0 -96
- package/dist/assets/ErrorBoundaryDoc-DoaAg68p.js +0 -111
- package/dist/assets/ExampleActionPlanPage-C0fIMZCD.js +0 -1
- package/dist/assets/ExampleAppDoc-DzIU81Fn.js +0 -1
- package/dist/assets/ExampleCard-DuLrb3t-.js +0 -1
- package/dist/assets/ExampleCrudReportsPage-M0pz6tdM.js +0 -1
- package/dist/assets/ExampleDashboardPage-CRG5r3Vw.js +0 -1
- package/dist/assets/ExampleIdeasPage-I84ZMLY4.js +0 -1
- package/dist/assets/ExampleImportWizardPage-h4YqrrSe.js +0 -1
- package/dist/assets/ExampleSettingsPage-CwdWqoaP.js +0 -1
- package/dist/assets/FileUploadDoc-9-UujFNX.js +0 -34
- package/dist/assets/FilterBar-DDTqqUfZ.js +0 -1
- package/dist/assets/FormDoc-CVES6n3d.js +0 -81
- package/dist/assets/FoundationOverview-DT0u11Gz.js +0 -1
- package/dist/assets/GridDoc-CbHFSILF.js +0 -28
- package/dist/assets/HooksDoc-Ctxdk6Wq.js +0 -665
- package/dist/assets/HoverCardDoc-8Wkaafdj.js +0 -31
- package/dist/assets/I18nDoc-D3Q2m7ik.js +0 -167
- package/dist/assets/IconPickerDoc-DZ26Gdpg.js +0 -10
- package/dist/assets/IconsFoundationDoc-xOxtC7CW.js +0 -33
- package/dist/assets/InputDoc-BhztAiuJ.js +0 -211
- package/dist/assets/LabelDoc-A4hmTRRV.js +0 -42
- package/dist/assets/LeadershipDoc-CqOSfWsP.js +0 -452
- package/dist/assets/MediaDoc-C78gvC8p.js +0 -459
- package/dist/assets/MenubarDoc-DCnmd2tO.js +0 -165
- package/dist/assets/ModuleAccessDoc-CmD5nHDp.js +0 -153
- package/dist/assets/ModulesDialogDoc-DVit1CA-.js +0 -46
- package/dist/assets/MultiselectPermissionsDoc-tlJMs04L.js +0 -34
- package/dist/assets/NavigationMenuDoc-q1fbc89j.js +0 -116
- package/dist/assets/OnboardingDialogDoc-3A3eBYrq.js +0 -55
- package/dist/assets/PaginationDoc-B8-bMz5J.js +0 -27
- package/dist/assets/PaginationDoc-BkGdxHL3.js +0 -98
- package/dist/assets/PlacesDoc-CKPO6ATs.js +0 -226
- package/dist/assets/PopoverDoc-CJPU4Ags.js +0 -64
- package/dist/assets/ProgressDoc-CpjbTL4o.js +0 -29
- package/dist/assets/QualiexUserFieldDoc-DDwumlRw.js +0 -149
- package/dist/assets/RadioGroupDoc-D6tSZz8G.js +0 -57
- package/dist/assets/RadiusDoc-B4xSnajw.js +0 -7
- package/dist/assets/ReportRequestListDoc-C0LIaU8P.js +0 -15
- package/dist/assets/RequiredFieldsCounterDoc-COesoSdx.js +0 -58
- package/dist/assets/ResizableDoc-CW0-XQuB.js +0 -104
- package/dist/assets/RichTextEditorDoc-C8c_XA9P.js +0 -24
- package/dist/assets/ScrollAreaDoc-BxtoAPaZ.js +0 -28
- package/dist/assets/SecurityDoc-wOVqpg2F.js +0 -204
- package/dist/assets/SelectDoc-C75gtY9D.js +0 -80
- package/dist/assets/SeparatorDoc-BjQBPB1P.js +0 -4
- package/dist/assets/ServicesDoc-CXTctwBl.js +0 -308
- package/dist/assets/ShadowsDoc-C6Lw8_x2.js +0 -9
- package/dist/assets/SignDoc-Bh5ZUg5x.js +0 -66
- package/dist/assets/SkeletonDoc-rTLGK5VE.js +0 -54
- package/dist/assets/SliderDoc-JMAMDub7.js +0 -41
- package/dist/assets/SpacingDoc-RljOrpwA.js +0 -12
- package/dist/assets/SplitButtonDoc-CvShUW3w.js +0 -53
- package/dist/assets/StepSelectorDoc-C-nAap9H.js +0 -41
- package/dist/assets/SwitchDoc-DLnqmkPr.js +0 -56
- package/dist/assets/TableDoc-B8EpWLVg.js +0 -128
- package/dist/assets/TabsDoc-DIBtl_uC.js +0 -42
- package/dist/assets/TeamSelectorDoc-B7OnCbL7.js +0 -10
- package/dist/assets/TermsOfUseDoc-Bb-pw08s.js +0 -16
- package/dist/assets/TextareaDoc-DGnqMqEC.js +0 -46
- package/dist/assets/ToastDoc-DjYyc7ae.js +0 -157
- package/dist/assets/ToggleDoc-C9ZOVjkY.js +0 -51
- package/dist/assets/TooltipDoc-BEx4l9-i.js +0 -58
- package/dist/assets/TruncatedCellDoc-BbV1bRSY.js +0 -12
- package/dist/assets/TypographyFoundationDoc-CUDYjRo9.js +0 -7
- package/dist/assets/UpdatesNotificationDoc-7nyjzLMJ.js +0 -29
- package/dist/assets/UsersGroupsSelectorDoc-C0KlTAL5.js +0 -18
- package/dist/assets/UtilitiesDoc-DGxaHVV1.js +0 -145
- package/dist/assets/ViewerDialogsDoc-CnTPTEz0.js +0 -1
- package/dist/assets/blocks-B6LrJeAM.js +0 -1
- package/dist/assets/building-DeVappnD.js +0 -1
- package/dist/assets/calendar-days-BQ0na5kM.js +0 -1
- package/dist/assets/check-check-C_-PJCJa.js +0 -1
- package/dist/assets/circle-plus-CpIcep-O.js +0 -1
- package/dist/assets/circle-x-jPpBPew0.js +0 -1
- package/dist/assets/clipboard-list-CXNPdciZ.js +0 -1
- package/dist/assets/cloud-upload-BEjzumjl.js +0 -1
- package/dist/assets/crown-CqNsQIsm.js +0 -1
- package/dist/assets/date-picker-BW3eGOe_.js +0 -1
- package/dist/assets/disabled-menu-item-C2YaMvSt.js +0 -1
- package/dist/assets/drawer-D5rflIcD.js +0 -3
- package/dist/assets/file-braces-DFb5X9so.js +0 -1
- package/dist/assets/file-pen-line-CyUGKkEN.js +0 -1
- package/dist/assets/git-branch-BcXv9mpp.js +0 -1
- package/dist/assets/globe-CpMIWAcv.js +0 -1
- package/dist/assets/hash-cQWdKjya.js +0 -1
- package/dist/assets/hourglass-BahQ3eDv.js +0 -1
- package/dist/assets/hover-card-R66N85sZ.js +0 -1
- package/dist/assets/iframe-dialog-V0mW5aBb.js +0 -1
- package/dist/assets/index-DkiftrvI.js +0 -352
- package/dist/assets/index-nmBjO9Th.css +0 -1
- package/dist/assets/life-buoy-ByXiPddz.js +0 -1
- package/dist/assets/loading-state-Cb5_t5uE.js +0 -1
- package/dist/assets/lucide-react-Cp3Yw3Zm.js +0 -1
- package/dist/assets/package-B3-pVvPM.js +0 -1
- package/dist/assets/pen-Bi_lmmKT.js +0 -1
- package/dist/assets/pin-DVsSl8QA.js +0 -1
- package/dist/assets/printer-BnJ8B6m-.js +0 -1
- package/dist/assets/radio-group-BHAaNGsm.js +0 -1
- package/dist/assets/server-CtzFTfKR.js +0 -1
- package/dist/assets/share-2-Dv8Do445.js +0 -1
- package/dist/assets/shield-check-CFXjOV_w.js +0 -1
- package/dist/assets/shield-x-DJTRfVux.js +0 -1
- package/dist/assets/slider-v9tXBSnB.js +0 -1
- package/dist/assets/smartphone-BSNR60L7.js +0 -1
- package/dist/assets/step-selector-ATTh_9Wa.js +0 -1
- package/dist/assets/text-align-start-qE-MbYYw.js +0 -1
- package/dist/assets/thumbs-up-D_XIW_uX.js +0 -1
- package/dist/assets/trash-DTWQwpwA.js +0 -1
- package/dist/assets/trending-up-jip5-leJ.js +0 -1
- package/dist/assets/useMockCrud-CN4vjyOZ.js +0 -1
- package/dist/assets/user-check-BlH3EDWK.js +0 -1
- package/dist/assets/user-plus-BqwXwD-c.js +0 -1
- package/dist/index.html +0 -33
|
@@ -1,665 +0,0 @@
|
|
|
1
|
-
import{r as t,j as e,em as W,x as N,B as C,dw as R,a as F,d as E,E as J,G as Z,H as X,I as Y,X as _,ew as T,S as B,ak as ee,al as ae,bk as se,an as te,ao as re,bs as I,o as L,ac as ie,J as S,W as U,K as A}from"./index-DkiftrvI.js";import{C as oe}from"./ComponentDocTemplate-CQbBhfvZ.js";import{R as ne,a as le}from"./radio-group-BHAaNGsm.js";import"./ExampleCard-DuLrb3t-.js";function de(p){const{steps:c,initialStep:g=0,initialData:b={},onComplete:v,onCancel:z}=p,[o,u]=t.useState(g),[h,a]=t.useState(b),[d,j]=t.useState(!1),[f,w]=t.useState(!1),l=c.length,y=o===0,s=o===l-1,r=c[o],x=l>1?(o+1)/l*100:100,m=t.useCallback(()=>r?.canProceed?r.canProceed():!0,[r]),M=t.useMemo(()=>m(),[m,h]),D=t.useMemo(()=>!(y||r?.disableBack),[y,r]),Q=t.useCallback(i=>{a(k=>({...k,...i}))},[]),q=t.useCallback((i,k)=>{a($=>({...$,[i]:k}))},[]),H=t.useCallback(()=>{u(g),a(b),j(!1),w(!1),z?.()},[g,b,z]),P=t.useCallback(async()=>{if(!(!m()||f)){w(!0);try{await v?.(h)}finally{w(!1)}}},[m,f,h,v]),G=t.useCallback(async()=>{!m()||d||(s?await P():u(i=>Math.min(i+1,l-1)))},[m,d,s,l,P]),V=t.useCallback(()=>{!D||d||u(i=>Math.max(i-1,0))},[D,d]),O=t.useCallback(i=>{i<0||i>=l||d||(i<=o||i===o+1)&&u(i)},[o,l,d]),K=t.useCallback(i=>{j(i)},[]);return{currentStep:o,currentStepConfig:r,data:h,isFirstStep:y,isLastStep:s,isLoading:d,isCompleting:f,next:G,back:V,goTo:O,canProceed:M,canGoBack:D,setData:Q,updateField:q,reset:H,complete:P,setLoading:K,progress:x,stepIndex:o,totalSteps:l}}const ce=`import {
|
|
2
|
-
useDebounce,
|
|
3
|
-
useActiveModules,
|
|
4
|
-
usePermissionQuery,
|
|
5
|
-
useI18nFormatters,
|
|
6
|
-
usePageTitle,
|
|
7
|
-
useColumnResize,
|
|
8
|
-
useRowResize,
|
|
9
|
-
useSidebarResize,
|
|
10
|
-
useQualiexUsers,
|
|
11
|
-
useWizard
|
|
12
|
-
} from 'forlogic-core/modular';`;function ue(){const[p,c]=t.useState(!1),[g,b]=t.useState(!1),[v,z]=t.useState(null),o={name:"",email:"",plan:"basic",notifications:!0,newsletter:!1},u=t.useRef(o),h=t.useMemo(()=>[{id:"personal",label:"Dados Pessoais",canProceed:()=>{const s=u.current;return s.name.length>=2&&s.email.includes("@")}},{id:"plan",label:"Escolha do Plano",canProceed:()=>!!u.current.plan},{id:"preferences",label:"Preferências"},{id:"review",label:"Confirmação"}],[]),a=de({steps:h,initialData:o,onComplete:async s=>{await new Promise(r=>setTimeout(r,1e3)),z(s),b(!0),c(!1)},onCancel:()=>{c(!1)}});u.current=a.data;const d=()=>{a.reset(),b(!1),z(null),c(!0)},j=h.map(s=>s.label),f={basic:{name:"Básico",price:"Grátis",features:["5 projetos","Suporte por email"]},pro:{name:"Pro",price:"R$ 49/mês",features:["Projetos ilimitados","Suporte prioritário","API access"]},enterprise:{name:"Enterprise",price:"Personalizado",features:["Tudo do Pro","SLA dedicado","Consultoria"]}},w=[e.jsx(T,{className:"h-5 w-5"}),e.jsx(W,{className:"h-5 w-5"}),e.jsx(B,{className:"h-5 w-5"}),e.jsx(R,{className:"h-5 w-5"})],l=()=>{switch(a.currentStep){case 0:return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[e.jsx("div",{className:"p-3 rounded-full bg-primary/10 text-primary",children:e.jsx(T,{className:"h-6 w-6"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold",children:"Seus dados"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Preencha suas informações básicas"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{htmlFor:"name",children:"Nome *"}),e.jsx(A,{id:"name",value:a.data.name,onChange:s=>a.updateField("name",s.target.value),placeholder:"Seu nome completo"}),a.data.name.length>0&&a.data.name.length<2&&e.jsx("p",{className:"text-xs text-destructive",children:"Nome deve ter pelo menos 2 caracteres"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(S,{htmlFor:"email",children:"Email *"}),e.jsx(A,{id:"email",type:"email",value:a.data.email,onChange:s=>a.updateField("email",s.target.value),placeholder:"seu@email.com"}),a.data.email.length>0&&!a.data.email.includes("@")&&e.jsx("p",{className:"text-xs text-destructive",children:"Email inválido"})]})]});case 1:return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[e.jsx("div",{className:"p-3 rounded-full bg-primary/10 text-primary",children:e.jsx(W,{className:"h-6 w-6"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold",children:"Escolha seu plano"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Selecione o plano que melhor atende suas necessidades"})]})]}),e.jsx(ne,{value:a.data.plan,onValueChange:s=>a.updateField("plan",s),className:"space-y-3",children:Object.entries(f).map(([s,r])=>e.jsxs("label",{className:L("flex items-start gap-4 p-4 rounded-lg border-2 cursor-pointer transition-all",a.data.plan===s?"border-primary bg-primary/5":"border-border hover:border-muted-foreground/50"),children:[e.jsx(le,{value:s,className:"mt-1"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"font-medium",children:r.name}),e.jsx(C,{variant:s==="pro"?"default":"outline",children:r.price})]}),e.jsx("ul",{className:"mt-2 space-y-1",children:r.features.map((x,m)=>e.jsxs("li",{className:"text-sm text-muted-foreground flex items-center gap-2",children:[e.jsx(I,{className:"h-3 w-3 text-green-500"})," ",x]},m))})]})]},s))})]});case 2:return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[e.jsx("div",{className:"p-3 rounded-full bg-primary/10 text-primary",children:e.jsx(B,{className:"h-6 w-6"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold",children:"Preferências"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Configure suas preferências de comunicação"})]})]}),e.jsx(F,{children:e.jsxs(E,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(S,{htmlFor:"notifications",className:"font-medium",children:"Notificações"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Receber notificações sobre atualizações"})]}),e.jsx(U,{id:"notifications",checked:a.data.notifications,onCheckedChange:s=>a.updateField("notifications",s)})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx(S,{htmlFor:"newsletter",className:"font-medium",children:"Newsletter"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Receber dicas e novidades por email"})]}),e.jsx(U,{id:"newsletter",checked:a.data.newsletter,onCheckedChange:s=>a.updateField("newsletter",s)})]})]})})]});case 3:return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[e.jsx("div",{className:"p-3 rounded-full bg-green-100 text-green-600",children:e.jsx(R,{className:"h-6 w-6"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold",children:"Confirme seus dados"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Revise as informações antes de finalizar"})]})]}),e.jsx(F,{children:e.jsxs(E,{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Nome"}),e.jsx("p",{className:"font-medium",children:a.data.name})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Email"}),e.jsx("p",{className:"font-medium",children:a.data.email})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Plano"}),e.jsx(C,{children:f[a.data.plan].name})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Preço"}),e.jsx("p",{className:"font-medium",children:f[a.data.plan].price})]})]}),e.jsxs("div",{className:"pt-3 border-t",children:[e.jsx("p",{className:"text-sm text-muted-foreground mb-2",children:"Preferências"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(C,{variant:a.data.notifications?"default":"outline",children:["Notificações: ",a.data.notifications?"Sim":"Não"]}),e.jsxs(C,{variant:a.data.newsletter?"default":"outline",children:["Newsletter: ",a.data.newsletter?"Sim":"Não"]})]})]})]})})]});default:return null}},y=()=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs(ee,{children:[e.jsx(ae,{asChild:!0,children:e.jsxs(N,{variant:"ghost",size:"sm",className:"h-auto py-1 px-2 text-sm text-muted-foreground hover:text-foreground",children:["Etapa ",a.currentStep+1,"/",a.totalSteps,e.jsx(se,{className:"h-3 w-3 ml-1"})]})}),e.jsx(te,{align:"start",children:j.map((s,r)=>{const x=r>a.currentStep;return e.jsxs(re,{onClick:()=>!x&&a.goTo(r),disabled:x,className:L("cursor-pointer",r===a.currentStep&&"bg-muted font-medium",x&&"opacity-50 cursor-not-allowed"),children:[e.jsxs("span",{className:"mr-2 text-muted-foreground",children:[r+1,"."]}),s,r===a.currentStep&&e.jsx(I,{className:"h-4 w-4 ml-auto"})]},r)})})]}),e.jsx(ie,{value:a.progress,className:"w-32 h-2"})]});return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx(N,{onClick:d,children:"Abrir Wizard de Cadastro"}),g&&v&&e.jsxs(C,{variant:"outline",className:"text-green-600 border-green-600",children:[e.jsx(R,{className:"h-3 w-3 mr-1"}),"Cadastro concluído!"]})]}),v&&e.jsx(F,{className:"bg-muted/50",children:e.jsxs(E,{className:"p-4",children:[e.jsx("p",{className:"text-sm font-medium mb-2",children:"Dados enviados:"}),e.jsx("pre",{className:"text-xs bg-background p-2 rounded overflow-x-auto",children:JSON.stringify(v,null,2)})]})}),e.jsx(J,{open:p,onOpenChange:s=>!s&&a.reset(),children:e.jsxs(Z,{size:"md",children:[e.jsxs(X,{showSeparator:!0,children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs(Y,{className:"flex items-center gap-2",children:[w[a.currentStep],a.currentStepConfig.label]})}),e.jsx(y,{})]}),e.jsx("div",{className:"flex-1 min-h-0 overflow-auto py-4 px-1 -mx-1",children:l()}),e.jsxs(_,{children:[a.canGoBack&&e.jsx(N,{variant:"outline",onClick:a.back,disabled:a.isCompleting,children:"Voltar"}),e.jsx(N,{onClick:a.next,disabled:!a.canProceed||a.isCompleting,children:a.isCompleting?"Finalizando...":a.isLastStep?"Finalizar Cadastro":"Próximo"})]})]})})]})}const me=`import { useDebounce } from 'forlogic-core/modular';
|
|
13
|
-
|
|
14
|
-
function SearchInput() {
|
|
15
|
-
const [searchTerm, setSearchTerm] = useState('');
|
|
16
|
-
const [debouncedSearch, cancelDebounce] = useDebounce(searchTerm, 500);
|
|
17
|
-
|
|
18
|
-
// API é chamada apenas quando usuário para de digitar por 500ms
|
|
19
|
-
const { data } = useQuery({
|
|
20
|
-
queryKey: ['search', debouncedSearch],
|
|
21
|
-
queryFn: () => api.search(debouncedSearch),
|
|
22
|
-
enabled: debouncedSearch.length > 0
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<Input
|
|
27
|
-
value={searchTerm}
|
|
28
|
-
onChange={(e) => setSearchTerm(e.target.value)}
|
|
29
|
-
placeholder="Buscar..."
|
|
30
|
-
/>
|
|
31
|
-
);
|
|
32
|
-
}`,pe=`import { useActiveModules } from 'forlogic-core/modular';
|
|
33
|
-
|
|
34
|
-
function App() {
|
|
35
|
-
const { data: modules, isLoading } = useActiveModules();
|
|
36
|
-
|
|
37
|
-
const hasTrainingModule = modules?.some(m => m.name === 'training');
|
|
38
|
-
|
|
39
|
-
if (isLoading) return <Spinner />;
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<nav>
|
|
43
|
-
{hasTrainingModule && <Link to="/training">Treinamentos</Link>}
|
|
44
|
-
</nav>
|
|
45
|
-
);
|
|
46
|
-
}`,ge=`import { usePermissionQuery } from 'forlogic-core/modular';
|
|
47
|
-
import { useAuth } from 'forlogic-core';
|
|
48
|
-
|
|
49
|
-
function ProtectedPage() {
|
|
50
|
-
const { isAuthenticated } = useAuth();
|
|
51
|
-
|
|
52
|
-
const { data: hasAccess, isLoading } = usePermissionQuery({
|
|
53
|
-
key: 'can-manage-users',
|
|
54
|
-
enabled: isAuthenticated,
|
|
55
|
-
checkFn: async () => {
|
|
56
|
-
const response = await fetch('/api/permissions/manage-users');
|
|
57
|
-
return response.ok;
|
|
58
|
-
},
|
|
59
|
-
staleTime: 5 * 60 * 1000 // Cache por 5 minutos
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
if (isLoading) return <div>Verificando permissões...</div>;
|
|
63
|
-
if (!hasAccess) return <div>Acesso negado</div>;
|
|
64
|
-
|
|
65
|
-
return <div>Conteúdo protegido</div>;
|
|
66
|
-
}`,he=`import { useI18nFormatters } from 'forlogic-core/modular';
|
|
67
|
-
|
|
68
|
-
function DateDisplay({ date }: { date: string }) {
|
|
69
|
-
const { formatDatetime, formatDate, locale, timezone } = useI18nFormatters();
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<div>
|
|
73
|
-
<p>Data: {formatDate(date)}</p>
|
|
74
|
-
<p>Data e hora: {formatDatetime(date)}</p>
|
|
75
|
-
<p>Locale: {locale}, Timezone: {timezone}</p>
|
|
76
|
-
</div>
|
|
77
|
-
);
|
|
78
|
-
}`,fe=`import { usePageTitle } from 'forlogic-core/modular';
|
|
79
|
-
|
|
80
|
-
function PageHeader() {
|
|
81
|
-
const title = usePageTitle();
|
|
82
|
-
|
|
83
|
-
return <h1>{title}</h1>;
|
|
84
|
-
// Se pathname for '/employees', retorna 'Funcionários'
|
|
85
|
-
// Se pathname for '/m', retorna 'Gestão'
|
|
86
|
-
// Se não encontrar, retorna 'Página'
|
|
87
|
-
}`,xe=`import { useColumnResize } from 'forlogic-core/modular';
|
|
88
|
-
|
|
89
|
-
function ResizableTable() {
|
|
90
|
-
const columns = [
|
|
91
|
-
{ key: 'name', minWidth: 100, maxWidth: 300, defaultWidth: 150 },
|
|
92
|
-
{ key: 'email', minWidth: 150, maxWidth: 400, defaultWidth: 200 },
|
|
93
|
-
{ key: 'status', minWidth: 80, maxWidth: 150, defaultWidth: 100 },
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
const {
|
|
97
|
-
columnWidths,
|
|
98
|
-
isDragging,
|
|
99
|
-
handleMouseDown,
|
|
100
|
-
resetWidths
|
|
101
|
-
} = useColumnResize({
|
|
102
|
-
columns,
|
|
103
|
-
storageKey: 'my-table-columns',
|
|
104
|
-
enabled: true
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return (
|
|
108
|
-
<table>
|
|
109
|
-
<thead>
|
|
110
|
-
<tr>
|
|
111
|
-
{columns.map((col) => (
|
|
112
|
-
<th
|
|
113
|
-
key={col.key}
|
|
114
|
-
style={{ width: columnWidths[col.key] }}
|
|
115
|
-
>
|
|
116
|
-
{col.key}
|
|
117
|
-
<div
|
|
118
|
-
onMouseDown={() => handleMouseDown(col.key)}
|
|
119
|
-
className="resize-handle"
|
|
120
|
-
/>
|
|
121
|
-
</th>
|
|
122
|
-
))}
|
|
123
|
-
</tr>
|
|
124
|
-
</thead>
|
|
125
|
-
</table>
|
|
126
|
-
);
|
|
127
|
-
}`,be=`import { useRowResize } from 'forlogic-core/modular';
|
|
128
|
-
|
|
129
|
-
function ResizableRows() {
|
|
130
|
-
const rowIds = ['row-1', 'row-2', 'row-3'];
|
|
131
|
-
|
|
132
|
-
const {
|
|
133
|
-
getRowHeight,
|
|
134
|
-
isDragging,
|
|
135
|
-
handleMouseDown
|
|
136
|
-
} = useRowResize({
|
|
137
|
-
rowIds,
|
|
138
|
-
minHeight: 40,
|
|
139
|
-
maxHeight: 200,
|
|
140
|
-
defaultHeight: 60,
|
|
141
|
-
storageKey: 'my-rows-height'
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<div>
|
|
146
|
-
{rowIds.map((id) => (
|
|
147
|
-
<div
|
|
148
|
-
key={id}
|
|
149
|
-
style={{ height: getRowHeight(id) }}
|
|
150
|
-
className="border-b"
|
|
151
|
-
>
|
|
152
|
-
Conteúdo da linha
|
|
153
|
-
<div onMouseDown={() => handleMouseDown(id)} className="resize-handle" />
|
|
154
|
-
</div>
|
|
155
|
-
))}
|
|
156
|
-
</div>
|
|
157
|
-
);
|
|
158
|
-
}`,ve=`import { useSidebarResize } from 'forlogic-core/modular';
|
|
159
|
-
|
|
160
|
-
function ResizableSidebar() {
|
|
161
|
-
const {
|
|
162
|
-
width,
|
|
163
|
-
isDragging,
|
|
164
|
-
handleMouseDown
|
|
165
|
-
} = useSidebarResize({
|
|
166
|
-
direction: 'right',
|
|
167
|
-
minWidth: 224,
|
|
168
|
-
maxWidth: 384,
|
|
169
|
-
defaultWidth: 240,
|
|
170
|
-
storageKey: 'sidebar-width',
|
|
171
|
-
isOpen: true
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
return (
|
|
175
|
-
<aside style={{ width }} className="sidebar-container">
|
|
176
|
-
<nav>...</nav>
|
|
177
|
-
<div
|
|
178
|
-
onMouseDown={handleMouseDown}
|
|
179
|
-
className="resize-handle absolute right-0 top-0 h-full w-1 cursor-ew-resize"
|
|
180
|
-
/>
|
|
181
|
-
</aside>
|
|
182
|
-
);
|
|
183
|
-
}`,ze=`import { useQualiexUsers } from 'forlogic-core/modular';
|
|
184
|
-
|
|
185
|
-
// ✅ Uso padrão - Busca automática ao montar
|
|
186
|
-
function UserList() {
|
|
187
|
-
const { data: users, isLoading, error } = useQualiexUsers();
|
|
188
|
-
|
|
189
|
-
if (isLoading) return <Spinner />;
|
|
190
|
-
if (error) return <div>Erro ao carregar usuários</div>;
|
|
191
|
-
|
|
192
|
-
return (
|
|
193
|
-
<ul>
|
|
194
|
-
{users?.map(user => (
|
|
195
|
-
<li key={user.id || user.userId}>
|
|
196
|
-
{user.displayName || user.userName} - {user.userEmail}
|
|
197
|
-
</li>
|
|
198
|
-
))}
|
|
199
|
-
</ul>
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// ✅ Busca condicional - Apenas quando modal está aberto
|
|
204
|
-
function UserSelectModal({ isOpen }: { isOpen: boolean }) {
|
|
205
|
-
const { data: users, isLoading } = useQualiexUsers({
|
|
206
|
-
enabled: isOpen // Só busca quando modal abre
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
return (
|
|
210
|
-
<Modal open={isOpen}>
|
|
211
|
-
{isLoading ? <Spinner /> : (
|
|
212
|
-
<select>
|
|
213
|
-
{users?.map(user => (
|
|
214
|
-
<option key={user.id} value={user.id}>
|
|
215
|
-
{user.displayName}
|
|
216
|
-
</option>
|
|
217
|
-
))}
|
|
218
|
-
</select>
|
|
219
|
-
)}
|
|
220
|
-
</Modal>
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// ✅ Lazy loading com refetch manual
|
|
225
|
-
function LazyUserLoader() {
|
|
226
|
-
const { data: users, refetch, isFetching } = useQualiexUsers({
|
|
227
|
-
enabled: false // Não busca automaticamente
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
const handleLoadUsers = async () => {
|
|
231
|
-
await refetch(); // Busca quando usuário clica
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
return (
|
|
235
|
-
<div>
|
|
236
|
-
<Button onClick={handleLoadUsers} disabled={isFetching}>
|
|
237
|
-
{isFetching ? 'Carregando...' : 'Carregar Usuários'}
|
|
238
|
-
</Button>
|
|
239
|
-
{users && <UserList users={users} />}
|
|
240
|
-
</div>
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Retorno do hook (UseQueryResult<QualiexUser[]>):
|
|
245
|
-
// - data: QualiexUser[] | undefined
|
|
246
|
-
// - isLoading: boolean (carregando pela primeira vez)
|
|
247
|
-
// - isFetching: boolean (qualquer requisição em andamento)
|
|
248
|
-
// - error: Error | null
|
|
249
|
-
// - refetch: () => Promise<...> (reexecutar query)
|
|
250
|
-
// - isSuccess: boolean
|
|
251
|
-
// - isError: boolean`,we=`import { useWizard, WizardStep } from 'forlogic-core';
|
|
252
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Button, Input, Progress } from 'forlogic-core';
|
|
253
|
-
|
|
254
|
-
interface PlanData {
|
|
255
|
-
name: string;
|
|
256
|
-
type: 'basic' | 'premium';
|
|
257
|
-
features: string[];
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function CreatePlanWizard({ open, onClose }: { open: boolean; onClose: () => void }) {
|
|
261
|
-
const steps: WizardStep[] = [
|
|
262
|
-
{
|
|
263
|
-
id: 'info',
|
|
264
|
-
label: 'Informações',
|
|
265
|
-
canProceed: () => wizard.data.name?.length > 0
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
id: 'type',
|
|
269
|
-
label: 'Tipo do Plano',
|
|
270
|
-
canProceed: () => !!wizard.data.type
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
id: 'features',
|
|
274
|
-
label: 'Funcionalidades',
|
|
275
|
-
canProceed: () => wizard.data.features?.length > 0
|
|
276
|
-
},
|
|
277
|
-
{ id: 'review', label: 'Revisão' },
|
|
278
|
-
];
|
|
279
|
-
|
|
280
|
-
const wizard = useWizard<PlanData>({
|
|
281
|
-
steps,
|
|
282
|
-
initialData: { name: '', type: 'basic', features: [] },
|
|
283
|
-
onComplete: async (data) => {
|
|
284
|
-
await api.createPlan(data);
|
|
285
|
-
onClose();
|
|
286
|
-
},
|
|
287
|
-
onCancel: onClose,
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
const renderStep = () => {
|
|
291
|
-
switch (wizard.currentStep) {
|
|
292
|
-
case 0:
|
|
293
|
-
return (
|
|
294
|
-
<Input
|
|
295
|
-
value={wizard.data.name}
|
|
296
|
-
onChange={(e) => wizard.updateField('name', e.target.value)}
|
|
297
|
-
placeholder="Nome do plano"
|
|
298
|
-
/>
|
|
299
|
-
);
|
|
300
|
-
case 1:
|
|
301
|
-
return (
|
|
302
|
-
<RadioGroup
|
|
303
|
-
value={wizard.data.type}
|
|
304
|
-
onValueChange={(v) => wizard.updateField('type', v as 'basic' | 'premium')}
|
|
305
|
-
>
|
|
306
|
-
<RadioGroupItem value="basic" label="Básico" />
|
|
307
|
-
<RadioGroupItem value="premium" label="Premium" />
|
|
308
|
-
</RadioGroup>
|
|
309
|
-
);
|
|
310
|
-
case 2:
|
|
311
|
-
return <FeatureSelector data={wizard.data} setData={wizard.setData} />;
|
|
312
|
-
case 3:
|
|
313
|
-
return <ReviewStep data={wizard.data} />;
|
|
314
|
-
default:
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
return (
|
|
320
|
-
<Dialog open={open} onOpenChange={() => wizard.reset()}>
|
|
321
|
-
<DialogContent size="md">
|
|
322
|
-
<DialogHeader>
|
|
323
|
-
<DialogTitle>{wizard.currentStepConfig.label}</DialogTitle>
|
|
324
|
-
<Progress value={wizard.progress} className="h-1" />
|
|
325
|
-
</DialogHeader>
|
|
326
|
-
|
|
327
|
-
<div className="py-4">{renderStep()}</div>
|
|
328
|
-
|
|
329
|
-
<DialogFooter>
|
|
330
|
-
{wizard.canGoBack && (
|
|
331
|
-
<Button variant="outline" onClick={wizard.back}>
|
|
332
|
-
Voltar
|
|
333
|
-
</Button>
|
|
334
|
-
)}
|
|
335
|
-
<Button
|
|
336
|
-
onClick={wizard.next}
|
|
337
|
-
disabled={!wizard.canProceed || wizard.isCompleting}
|
|
338
|
-
>
|
|
339
|
-
{wizard.isLastStep ? 'Concluir' : 'Próximo'}
|
|
340
|
-
</Button>
|
|
341
|
-
</DialogFooter>
|
|
342
|
-
</DialogContent>
|
|
343
|
-
</Dialog>
|
|
344
|
-
);
|
|
345
|
-
}`,ye=`import { useWizard, WizardStep } from 'forlogic-core';
|
|
346
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Button, Input, Alert } from 'forlogic-core';
|
|
347
|
-
import { useState } from 'react';
|
|
348
|
-
|
|
349
|
-
interface UserData {
|
|
350
|
-
email: string;
|
|
351
|
-
username: string;
|
|
352
|
-
password: string;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function RegisterWizard({ open, onClose }: { open: boolean; onClose: () => void }) {
|
|
356
|
-
const [emailError, setEmailError] = useState<string | null>(null);
|
|
357
|
-
const [usernameError, setUsernameError] = useState<string | null>(null);
|
|
358
|
-
|
|
359
|
-
// Validação assíncrona de email
|
|
360
|
-
const validateEmail = async (email: string): Promise<boolean> => {
|
|
361
|
-
wizard.setLoading(true);
|
|
362
|
-
setEmailError(null);
|
|
363
|
-
|
|
364
|
-
try {
|
|
365
|
-
const response = await fetch(\`/api/check-email?email=\${encodeURIComponent(email)}\`);
|
|
366
|
-
const { available } = await response.json();
|
|
367
|
-
|
|
368
|
-
if (!available) {
|
|
369
|
-
setEmailError('Este email já está em uso');
|
|
370
|
-
return false;
|
|
371
|
-
}
|
|
372
|
-
return true;
|
|
373
|
-
} catch (error) {
|
|
374
|
-
setEmailError('Erro ao verificar email');
|
|
375
|
-
return false;
|
|
376
|
-
} finally {
|
|
377
|
-
wizard.setLoading(false);
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
// Validação assíncrona de username
|
|
382
|
-
const validateUsername = async (username: string): Promise<boolean> => {
|
|
383
|
-
wizard.setLoading(true);
|
|
384
|
-
setUsernameError(null);
|
|
385
|
-
|
|
386
|
-
try {
|
|
387
|
-
const response = await fetch(\`/api/check-username?username=\${encodeURIComponent(username)}\`);
|
|
388
|
-
const { available } = await response.json();
|
|
389
|
-
|
|
390
|
-
if (!available) {
|
|
391
|
-
setUsernameError('Este nome de usuário já está em uso');
|
|
392
|
-
return false;
|
|
393
|
-
}
|
|
394
|
-
return true;
|
|
395
|
-
} catch (error) {
|
|
396
|
-
setUsernameError('Erro ao verificar nome de usuário');
|
|
397
|
-
return false;
|
|
398
|
-
} finally {
|
|
399
|
-
wizard.setLoading(false);
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
const steps: WizardStep[] = [
|
|
404
|
-
{
|
|
405
|
-
id: 'email',
|
|
406
|
-
label: 'Email',
|
|
407
|
-
canProceed: () => wizard.data.email?.includes('@') && !emailError
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
id: 'username',
|
|
411
|
-
label: 'Usuário',
|
|
412
|
-
canProceed: () => wizard.data.username?.length >= 3 && !usernameError
|
|
413
|
-
},
|
|
414
|
-
{
|
|
415
|
-
id: 'password',
|
|
416
|
-
label: 'Senha',
|
|
417
|
-
canProceed: () => wizard.data.password?.length >= 8
|
|
418
|
-
},
|
|
419
|
-
];
|
|
420
|
-
|
|
421
|
-
const wizard = useWizard<UserData>({
|
|
422
|
-
steps,
|
|
423
|
-
initialData: { email: '', username: '', password: '' },
|
|
424
|
-
onComplete: async (data) => {
|
|
425
|
-
await api.register(data);
|
|
426
|
-
onClose();
|
|
427
|
-
},
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
// Handler customizado para próximo com validação assíncrona
|
|
431
|
-
const handleNext = async () => {
|
|
432
|
-
if (wizard.currentStep === 0) {
|
|
433
|
-
const isValid = await validateEmail(wizard.data.email);
|
|
434
|
-
if (!isValid) return;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
if (wizard.currentStep === 1) {
|
|
438
|
-
const isValid = await validateUsername(wizard.data.username);
|
|
439
|
-
if (!isValid) return;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
wizard.next();
|
|
443
|
-
};
|
|
444
|
-
|
|
445
|
-
return (
|
|
446
|
-
<Dialog open={open} onOpenChange={() => wizard.reset()}>
|
|
447
|
-
<DialogContent size="sm">
|
|
448
|
-
<DialogHeader showSeparator>
|
|
449
|
-
<DialogTitle>Criar conta - {wizard.currentStepConfig.label}</DialogTitle>
|
|
450
|
-
</DialogHeader>
|
|
451
|
-
|
|
452
|
-
<div className="py-4 space-y-4">
|
|
453
|
-
{wizard.currentStep === 0 && (
|
|
454
|
-
<>
|
|
455
|
-
<Input
|
|
456
|
-
value={wizard.data.email}
|
|
457
|
-
onChange={(e) => {
|
|
458
|
-
wizard.updateField('email', e.target.value);
|
|
459
|
-
setEmailError(null);
|
|
460
|
-
}}
|
|
461
|
-
placeholder="seu@email.com"
|
|
462
|
-
type="email"
|
|
463
|
-
/>
|
|
464
|
-
{emailError && <Alert variant="destructive">{emailError}</Alert>}
|
|
465
|
-
</>
|
|
466
|
-
)}
|
|
467
|
-
|
|
468
|
-
{wizard.currentStep === 1 && (
|
|
469
|
-
<>
|
|
470
|
-
<Input
|
|
471
|
-
value={wizard.data.username}
|
|
472
|
-
onChange={(e) => {
|
|
473
|
-
wizard.updateField('username', e.target.value);
|
|
474
|
-
setUsernameError(null);
|
|
475
|
-
}}
|
|
476
|
-
placeholder="Nome de usuário"
|
|
477
|
-
/>
|
|
478
|
-
{usernameError && <Alert variant="destructive">{usernameError}</Alert>}
|
|
479
|
-
</>
|
|
480
|
-
)}
|
|
481
|
-
|
|
482
|
-
{wizard.currentStep === 2 && (
|
|
483
|
-
<Input
|
|
484
|
-
value={wizard.data.password}
|
|
485
|
-
onChange={(e) => wizard.updateField('password', e.target.value)}
|
|
486
|
-
placeholder="Senha (mínimo 8 caracteres)"
|
|
487
|
-
type="password"
|
|
488
|
-
/>
|
|
489
|
-
)}
|
|
490
|
-
</div>
|
|
491
|
-
|
|
492
|
-
<DialogFooter>
|
|
493
|
-
{wizard.canGoBack && (
|
|
494
|
-
<Button variant="outline" onClick={wizard.back} disabled={wizard.isLoading}>
|
|
495
|
-
Voltar
|
|
496
|
-
</Button>
|
|
497
|
-
)}
|
|
498
|
-
<Button
|
|
499
|
-
onClick={handleNext}
|
|
500
|
-
disabled={!wizard.canProceed || wizard.isLoading || wizard.isCompleting}
|
|
501
|
-
>
|
|
502
|
-
{wizard.isLoading ? 'Validando...' : wizard.isLastStep ? 'Criar conta' : 'Próximo'}
|
|
503
|
-
</Button>
|
|
504
|
-
</DialogFooter>
|
|
505
|
-
</DialogContent>
|
|
506
|
-
</Dialog>
|
|
507
|
-
);
|
|
508
|
-
}`,Ce=`import { useWizard, WizardStep } from 'forlogic-core';
|
|
509
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Button, BaseForm, StepSelector } from 'forlogic-core';
|
|
510
|
-
import { z } from 'zod';
|
|
511
|
-
|
|
512
|
-
// Schemas Zod para cada etapa
|
|
513
|
-
const personalInfoSchema = z.object({
|
|
514
|
-
firstName: z.string().min(2, 'Nome deve ter pelo menos 2 caracteres'),
|
|
515
|
-
lastName: z.string().min(2, 'Sobrenome deve ter pelo menos 2 caracteres'),
|
|
516
|
-
email: z.string().email('Email inválido'),
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
const addressSchema = z.object({
|
|
520
|
-
street: z.string().min(5, 'Endereço deve ter pelo menos 5 caracteres'),
|
|
521
|
-
city: z.string().min(2, 'Cidade é obrigatória'),
|
|
522
|
-
zipCode: z.string().regex(/^\\d{5}-?\\d{3}$/, 'CEP inválido'),
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
const preferencesSchema = z.object({
|
|
526
|
-
newsletter: z.boolean(),
|
|
527
|
-
notifications: z.boolean(),
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
interface FormData {
|
|
531
|
-
firstName: string;
|
|
532
|
-
lastName: string;
|
|
533
|
-
email: string;
|
|
534
|
-
street: string;
|
|
535
|
-
city: string;
|
|
536
|
-
zipCode: string;
|
|
537
|
-
newsletter: boolean;
|
|
538
|
-
notifications: boolean;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
function OnboardingWizard({ open, onClose }: { open: boolean; onClose: () => void }) {
|
|
542
|
-
const steps: WizardStep[] = [
|
|
543
|
-
{
|
|
544
|
-
id: 'personal',
|
|
545
|
-
label: 'Dados Pessoais',
|
|
546
|
-
canProceed: () => {
|
|
547
|
-
try {
|
|
548
|
-
personalInfoSchema.parse({
|
|
549
|
-
firstName: wizard.data.firstName,
|
|
550
|
-
lastName: wizard.data.lastName,
|
|
551
|
-
email: wizard.data.email,
|
|
552
|
-
});
|
|
553
|
-
return true;
|
|
554
|
-
} catch { return false; }
|
|
555
|
-
}
|
|
556
|
-
},
|
|
557
|
-
{
|
|
558
|
-
id: 'address',
|
|
559
|
-
label: 'Endereço',
|
|
560
|
-
canProceed: () => {
|
|
561
|
-
try {
|
|
562
|
-
addressSchema.parse({
|
|
563
|
-
street: wizard.data.street,
|
|
564
|
-
city: wizard.data.city,
|
|
565
|
-
zipCode: wizard.data.zipCode,
|
|
566
|
-
});
|
|
567
|
-
return true;
|
|
568
|
-
} catch { return false; }
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
{
|
|
572
|
-
id: 'preferences',
|
|
573
|
-
label: 'Preferências'
|
|
574
|
-
},
|
|
575
|
-
];
|
|
576
|
-
|
|
577
|
-
const wizard = useWizard<FormData>({
|
|
578
|
-
steps,
|
|
579
|
-
initialData: {
|
|
580
|
-
firstName: '',
|
|
581
|
-
lastName: '',
|
|
582
|
-
email: '',
|
|
583
|
-
street: '',
|
|
584
|
-
city: '',
|
|
585
|
-
zipCode: '',
|
|
586
|
-
newsletter: true,
|
|
587
|
-
notifications: true,
|
|
588
|
-
},
|
|
589
|
-
onComplete: async (data) => {
|
|
590
|
-
await api.completeOnboarding(data);
|
|
591
|
-
onClose();
|
|
592
|
-
},
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
const stepLabels = steps.map(s => s.label);
|
|
596
|
-
|
|
597
|
-
// Campos BaseForm para cada etapa
|
|
598
|
-
const personalFields = [
|
|
599
|
-
{ name: 'firstName', label: 'Nome', type: 'text' as const, required: true },
|
|
600
|
-
{ name: 'lastName', label: 'Sobrenome', type: 'text' as const, required: true },
|
|
601
|
-
{ name: 'email', label: 'Email', type: 'text' as const, required: true },
|
|
602
|
-
];
|
|
603
|
-
|
|
604
|
-
const addressFields = [
|
|
605
|
-
{ name: 'street', label: 'Endereço', type: 'text' as const, required: true },
|
|
606
|
-
{ name: 'city', label: 'Cidade', type: 'text' as const, required: true },
|
|
607
|
-
{ name: 'zipCode', label: 'CEP', type: 'text' as const, required: true, placeholder: '00000-000' },
|
|
608
|
-
];
|
|
609
|
-
|
|
610
|
-
const preferencesFields = [
|
|
611
|
-
{ name: 'newsletter', label: 'Receber newsletter', type: 'switch' as const },
|
|
612
|
-
{ name: 'notifications', label: 'Notificações por email', type: 'switch' as const },
|
|
613
|
-
];
|
|
614
|
-
|
|
615
|
-
const getCurrentFields = () => {
|
|
616
|
-
switch (wizard.currentStep) {
|
|
617
|
-
case 0: return personalFields;
|
|
618
|
-
case 1: return addressFields;
|
|
619
|
-
case 2: return preferencesFields;
|
|
620
|
-
default: return [];
|
|
621
|
-
}
|
|
622
|
-
};
|
|
623
|
-
|
|
624
|
-
return (
|
|
625
|
-
<Dialog open={open} onOpenChange={() => wizard.reset()}>
|
|
626
|
-
<DialogContent size="lg">
|
|
627
|
-
<DialogHeader showSeparator>
|
|
628
|
-
<DialogTitle>Configuração Inicial</DialogTitle>
|
|
629
|
-
<StepSelector
|
|
630
|
-
currentStep={wizard.currentStep}
|
|
631
|
-
totalSteps={wizard.totalSteps}
|
|
632
|
-
labels={stepLabels}
|
|
633
|
-
onStepClick={(step) => {
|
|
634
|
-
// Só permite voltar, não avançar clicando
|
|
635
|
-
if (step < wizard.currentStep) wizard.goTo(step);
|
|
636
|
-
}}
|
|
637
|
-
/>
|
|
638
|
-
</DialogHeader>
|
|
639
|
-
|
|
640
|
-
<div className="flex-1 min-h-0 overflow-auto py-4 px-1 -mx-1">
|
|
641
|
-
<BaseForm
|
|
642
|
-
fields={getCurrentFields()}
|
|
643
|
-
values={wizard.data}
|
|
644
|
-
onChange={(field, value) => wizard.updateField(field as keyof FormData, value)}
|
|
645
|
-
columns={2}
|
|
646
|
-
/>
|
|
647
|
-
</div>
|
|
648
|
-
|
|
649
|
-
<DialogFooter>
|
|
650
|
-
{wizard.canGoBack && (
|
|
651
|
-
<Button variant="outline" onClick={wizard.back}>
|
|
652
|
-
Voltar
|
|
653
|
-
</Button>
|
|
654
|
-
)}
|
|
655
|
-
<Button
|
|
656
|
-
onClick={wizard.next}
|
|
657
|
-
disabled={!wizard.canProceed || wizard.isCompleting}
|
|
658
|
-
>
|
|
659
|
-
{wizard.isCompleting ? 'Salvando...' : wizard.isLastStep ? 'Concluir' : 'Próximo'}
|
|
660
|
-
</Button>
|
|
661
|
-
</DialogFooter>
|
|
662
|
-
</DialogContent>
|
|
663
|
-
</Dialog>
|
|
664
|
-
);
|
|
665
|
-
}`,je=[{name:"useDebounce<T>(value, delay)",type:"[T, () => void]",default:"-",description:"Retorna [valor com debounce, função para cancelar]. Útil para otimizar chamadas de API em campos de busca."},{name:"useActiveModules(options?)",type:"UseQueryResult<Module[]>",default:"{ enabled: true }",description:"Busca módulos ativos da empresa/unidade. Usa cache do React Query."},{name:"usePermissionQuery(options)",type:"UseQueryResult<boolean>",default:"staleTime: 5min",description:"Verifica permissões com cache otimizado. Evita chamadas repetidas ao servidor."},{name:"useI18nFormatters()",type:"{ formatDatetime, formatDate, locale, timezone, datetimeFormat }",default:"-",description:"Formatação de datas com locale e timezone do usuário."},{name:"usePageTitle()",type:"string",default:"'Página'",description:"Retorna título da página atual baseado na rota do NavigationContext."},{name:"useColumnResize(options)",type:"{ columnWidths, isDragging, handleMouseDown, resetWidths }",default:"-",description:"Gerencia redimensionamento de colunas com persistência em localStorage."},{name:"useRowResize(options)",type:"{ getRowHeight, isDragging, handleMouseDown, resetHeights }",default:"-",description:"Gerencia redimensionamento de linhas com persistência em localStorage."},{name:"useSidebarResize(options)",type:"{ width, isDragging, handleMouseDown }",default:"minWidth: 224, maxWidth: 384",description:"Gerencia redimensionamento da sidebar com persistência e CSS variable."},{name:"useQualiexUsers(options?)",type:"UseQueryResult<QualiexUser[]>",default:"{ enabled: true }",description:"Busca usuários ativos da API Qualiex. Retorna apenas usuários com status ativo."},{name:"options.enabled",type:"boolean",default:"true",description:"Controla se a query executa. Use false para lazy loading com refetch() manual."},{name:"useWizard<TData>(options)",type:"UseWizardReturn<TData>",default:"-",description:"Gerencia estado completo de wizard: steps, navegação, validação e dados."},{name:"options.steps",type:"WizardStep[]",default:"-",description:"Array de steps com id, label e opcionalmente canProceed() e disableBack."},{name:"options.initialData",type:"TData",default:"{}",description:"Dados iniciais do wizard."},{name:"options.initialStep",type:"number",default:"0",description:"Índice do step inicial."},{name:"options.onComplete",type:"(data: TData) => void | Promise<void>",default:"-",description:"Callback executado ao concluir o wizard."},{name:"options.onCancel",type:"() => void",default:"-",description:"Callback executado ao cancelar/resetar o wizard."},{name:"return.currentStep",type:"number",default:"-",description:"Índice do step atual (0-indexed)."},{name:"return.currentStepConfig",type:"WizardStep",default:"-",description:"Configuração do step atual (id, label, canProceed, disableBack)."},{name:"return.data",type:"TData",default:"-",description:"Dados acumulados do wizard."},{name:"return.canProceed",type:"boolean",default:"-",description:"Se pode avançar (baseado em canProceed do step)."},{name:"return.canGoBack",type:"boolean",default:"-",description:"Se pode voltar (false se primeiro step ou disableBack)."},{name:"return.isLoading",type:"boolean",default:"-",description:"Estado de loading controlável via setLoading()."},{name:"return.isCompleting",type:"boolean",default:"-",description:"True durante execução do onComplete."},{name:"return.next()",type:"() => Promise<void>",default:"-",description:"Avança para próximo step ou executa onComplete no último."},{name:"return.back()",type:"() => void",default:"-",description:"Volta para step anterior."},{name:"return.goTo(step)",type:"(step: number) => void",default:"-",description:"Navega para step específico (apenas anteriores ou próximo)."},{name:"return.setData(data)",type:"(data: Partial<TData>) => void",default:"-",description:"Atualiza múltiplos campos de uma vez."},{name:"return.updateField(field, value)",type:"<K>(field: K, value: TData[K]) => void",default:"-",description:"Atualiza um campo específico."},{name:"return.reset()",type:"() => void",default:"-",description:"Reseta wizard para estado inicial e executa onCancel."},{name:"return.setLoading(loading)",type:"(loading: boolean) => void",default:"-",description:"Controla estado de loading (útil para validação assíncrona)."},{name:"return.progress",type:"number",default:"-",description:"Progresso em porcentagem (0-100)."},{name:"return.totalSteps",type:"number",default:"-",description:"Número total de steps."}];function n({title:p,description:c,code:g}){return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold",children:p}),e.jsx("p",{className:"text-sm text-muted-foreground",children:c})]}),e.jsx("pre",{className:"rounded-lg border bg-muted/50 p-4 overflow-x-auto",children:e.jsx("code",{className:"text-sm font-mono",children:g})})]})}function ke(){const p=[{id:"exemplos",label:"Exemplos"},{id:"usedebounce",label:"useDebounce"},{id:"useactivemodules",label:"useActiveModules"},{id:"usepermissionquery",label:"usePermissionQuery"},{id:"usei18nformatters",label:"useI18nFormatters"},{id:"usepagetitle",label:"usePageTitle"},{id:"usecolumnresize",label:"useColumnResize"},{id:"userowresize",label:"useRowResize"},{id:"usesidebarresize",label:"useSidebarResize"},{id:"usequaliexusers",label:"useQualiexUsers"},{id:"usewizard-preview",label:"useWizard - Preview"},{id:"usewizard-basico",label:"useWizard - Básico"},{id:"usewizard-async",label:"useWizard - Validação Assíncrona"},{id:"usewizard-baseform",label:"useWizard - BaseForm"}];return e.jsx(oe,{title:"Hooks",description:"Hooks utilitários da biblioteca forlogic-core para otimização, dados, formatação e UI. Todos os hooks seguem padrões React e são compatíveis com React Query quando aplicável.",usage:ce,props:je,tocItems:p,notes:["Todos os hooks de resize persistem automaticamente no localStorage usando a storageKey fornecida.","useDebounce retorna uma tupla com o valor debounced e uma função para cancelar o debounce pendente.","useActiveModules e usePermissionQuery utilizam React Query internamente para gerenciamento de cache.","useI18nFormatters depende do LocaleContext configurado via CoreProviders.","usePageTitle depende do NavigationContext com array de rotas configurado.","useQualiexUsers retorna apenas usuários ativos (filterStatus=active) e requer autenticação.",'useQualiexUsers usa queryKey ["qualiex-users", alias] para cache automático por unidade.',"useWizard gerencia estado completo de wizard e é ideal para uso com Dialog para criar formulários multi-etapas."],children:e.jsxs("div",{id:"exemplos",className:"space-y-8 scroll-mt-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Exemplos"}),e.jsx("div",{id:"usedebounce",className:"scroll-mt-4",children:e.jsx(n,{title:"useDebounce",description:"Aplica debounce em um valor com capacidade de cancelamento. Útil para otimizar chamadas de API em campos de busca.",code:me})}),e.jsx("div",{id:"useactivemodules",className:"scroll-mt-4",children:e.jsx(n,{title:"useActiveModules",description:"Busca módulos ativos da empresa/unidade atual. Usa cache do React Query para evitar chamadas repetidas.",code:pe})}),e.jsx("div",{id:"usepermissionquery",className:"scroll-mt-4",children:e.jsx(n,{title:"usePermissionQuery",description:"Verifica permissões com cache otimizado. Ideal para controle de acesso em páginas protegidas.",code:ge})}),e.jsx("div",{id:"usei18nformatters",className:"scroll-mt-4",children:e.jsx(n,{title:"useI18nFormatters",description:"Formatação de datas respeitando locale e timezone do usuário configurado no LocaleContext.",code:he})}),e.jsx("div",{id:"usepagetitle",className:"scroll-mt-4",children:e.jsx(n,{title:"usePageTitle",description:"Obtém título da página atual baseado na configuração do NavigationContext.",code:fe})}),e.jsx("div",{id:"usecolumnresize",className:"scroll-mt-4",children:e.jsx(n,{title:"useColumnResize",description:"Gerencia redimensionamento de colunas de tabela com persistência em localStorage.",code:xe})}),e.jsx("div",{id:"userowresize",className:"scroll-mt-4",children:e.jsx(n,{title:"useRowResize",description:"Gerencia redimensionamento de linhas com persistência em localStorage.",code:be})}),e.jsx("div",{id:"usesidebarresize",className:"scroll-mt-4",children:e.jsx(n,{title:"useSidebarResize",description:"Gerencia redimensionamento da sidebar com persistência e atualização de CSS variable.",code:ve})}),e.jsx("div",{id:"usequaliexusers",className:"scroll-mt-4",children:e.jsx(n,{title:"useQualiexUsers",description:"Busca usuários ativos da API Qualiex. Suporta busca automática, condicional ou lazy loading com refetch manual.",code:ze})}),e.jsxs("div",{id:"usewizard-preview",className:"space-y-4 p-6 border rounded-lg bg-card scroll-mt-4",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"text-lg font-semibold flex items-center gap-2",children:[e.jsx(W,{className:"h-5 w-5 text-primary"}),"useWizard - Preview Interativo"]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Experimente o wizard em funcionamento. Navegue pelas etapas, preencha os campos e veja a validação em tempo real."})]}),e.jsx(ue,{})]}),e.jsx("div",{id:"usewizard-basico",className:"scroll-mt-4",children:e.jsx(n,{title:"useWizard - Básico",description:"Gerencia estado completo de wizard: steps, navegação, validação, dados e callbacks. Ideal para formulários multi-etapas.",code:we})}),e.jsx("div",{id:"usewizard-async",className:"scroll-mt-4",children:e.jsx(n,{title:"useWizard - Validação Assíncrona",description:"Exemplo de wizard com validação assíncrona de campos (verificação de email/username disponível) usando setLoading() para controlar estados de carregamento.",code:ye})}),e.jsx("div",{id:"usewizard-baseform",className:"scroll-mt-4",children:e.jsx(n,{title:"useWizard - Integração com BaseForm",description:"Exemplo completo de wizard usando BaseForm para renderização de campos, StepSelector para navegação visual e validação Zod por etapa.",code:Ce})})]})})}export{ke as HooksDoc};
|