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.
Files changed (190) hide show
  1. package/.note/memory/features/crud-defaults-batteries-included.md +1 -1
  2. package/dist/components/ui/dialog-wizard.d.ts +82 -0
  3. package/dist/components/ui/input-group.d.ts +1 -1
  4. package/dist/components/ui/input.d.ts +5 -23
  5. package/dist/components/ui/resizable.d.ts +1 -1
  6. package/dist/components/ui/sidebar.d.ts +1 -1
  7. package/dist/components/ui/step-selector.d.ts +11 -9
  8. package/dist/components/ui/textarea.d.ts +1 -0
  9. package/dist/crud/components/CrudTable.d.ts +3 -1
  10. package/dist/crud/createCrudPage.d.ts +2 -0
  11. package/dist/crud/hooks/useColumnManager.d.ts +3 -1
  12. package/dist/exports/ui.d.ts +1 -0
  13. package/dist/index.css +1 -1
  14. package/dist/index.css.map +1 -1
  15. package/dist/index.esm.js +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/types.d.ts +3 -0
  18. package/docs/design-system/README.md +2 -2
  19. package/docs/design-system/buttons-actions.md +6 -0
  20. package/docs/design-system/domain.md +10 -0
  21. package/docs/design-system/inputs.md +20 -0
  22. package/docs/design-system/navigation.md +5 -0
  23. package/docs/design-system/notifications-feedback.md +2 -0
  24. package/package.json +1 -1
  25. package/dist/assets/AccordionDoc-CGNlubG3.js +0 -31
  26. package/dist/assets/ActionButtonDoc-CYtkXR0k.js +0 -47
  27. package/dist/assets/ActionPlanDoc-BSuPRftQ.js +0 -65
  28. package/dist/assets/AlertDoc-Cpvxneqg.js +0 -37
  29. package/dist/assets/AliasUrlDoc-DIpUWf4Y.js +0 -189
  30. package/dist/assets/AppHeaderDoc-DNQErj_t.js +0 -74
  31. package/dist/assets/AppSidebarDoc-DkeQarDu.js +0 -221
  32. package/dist/assets/ApprovalFlowDoc-8YgXbhKJ.js +0 -31
  33. package/dist/assets/AuditLogDoc-BBvNcHIo.js +0 -67
  34. package/dist/assets/AuditTrailDoc-DgFHO-uo.js +0 -17
  35. package/dist/assets/AuthDoc-WIA_Aetl.js +0 -200
  36. package/dist/assets/AvatarDoc-B6go1C1T.js +0 -11
  37. package/dist/assets/BadgeDoc-BONhfqB_.js +0 -36
  38. package/dist/assets/BaseFormDoc-CuyUArcj.js +0 -169
  39. package/dist/assets/BodyContentDoc-CterHC1E.js +0 -83
  40. package/dist/assets/BreadcrumbDoc-Dwn9nLeO.js +0 -75
  41. package/dist/assets/ButtonDoc-BOjRseZT.js +0 -41
  42. package/dist/assets/ButtonGroupDoc-8IS6PPh4.js +0 -7
  43. package/dist/assets/CalendarDoc-CMwIEqgT.js +0 -81
  44. package/dist/assets/CardDoc-BZz1CVg2.js +0 -49
  45. package/dist/assets/ChartDoc-B5vZVtqD.js +0 -76
  46. package/dist/assets/CheckboxDoc-lAbYO9I5.js +0 -55
  47. package/dist/assets/ColorPickerDoc-Dpsprp4N.js +0 -10
  48. package/dist/assets/ColorsFoundationDoc-CCHeSL3p.js +0 -13
  49. package/dist/assets/ComboTreeDoc-D4dTkIt-.js +0 -46
  50. package/dist/assets/ComboboxDoc-CqqZPvZq.js +0 -134
  51. package/dist/assets/ComponentDocTemplate-CQbBhfvZ.js +0 -1
  52. package/dist/assets/ContextMenuDoc-D3jC-MVA.js +0 -182
  53. package/dist/assets/ContextsDoc-XFH0-JdS.js +0 -211
  54. package/dist/assets/CreateCrudPageDoc-CpuiWI-g.js +0 -106
  55. package/dist/assets/CrudActionBarDoc-wuBGXD9Y.js +0 -112
  56. package/dist/assets/CrudGridDoc-BYWqSXBH.js +0 -85
  57. package/dist/assets/CrudOverviewDoc-B_bk2a2t.js +0 -14
  58. package/dist/assets/CrudPrimitivesDoc-CxaTB94A.js +0 -164
  59. package/dist/assets/CrudTableDoc-Dga1VgCu.js +0 -113
  60. package/dist/assets/CustomFormFieldsDoc-C1hwwSl3.js +0 -33
  61. package/dist/assets/DashboardFormDoc-BUDCmrMl.js +0 -49
  62. package/dist/assets/DashboardGeneralViewDoc-Cyg1SIiG.js +0 -71
  63. package/dist/assets/DashboardGridDoc-BavePiRF.js +0 -49
  64. package/dist/assets/DashboardListDoc-CLyMA6UK.js +0 -37
  65. package/dist/assets/DashboardOverviewDoc-DRVvNIF1.js +0 -35
  66. package/dist/assets/DashboardPanelRendererDoc--mfwb8Nc.js +0 -60
  67. package/dist/assets/DashboardPanelsBasicDoc-BQ2V_52D.js +0 -62
  68. package/dist/assets/DashboardPanelsCartesianDoc-sy-hcVQY.js +0 -75
  69. package/dist/assets/DashboardPanelsSpecialDoc-DsIUCRRP.js +0 -83
  70. package/dist/assets/DashboardViewDoc-CtlCNlEF.js +0 -45
  71. package/dist/assets/DataListDoc-DUy88lCQ.js +0 -13
  72. package/dist/assets/DesignSystemHome-DHl9YtbH.js +0 -1
  73. package/dist/assets/DialogDoc-CMQqnTV-.js +0 -981
  74. package/dist/assets/DropdownMenuDoc-S7X9csGt.js +0 -175
  75. package/dist/assets/ElectronicSignatureDialogDoc-BfithaL_.js +0 -57
  76. package/dist/assets/EmptyStateDoc-CHGCiGIk.js +0 -35
  77. package/dist/assets/EnvironmentsDoc-DZHJZ2nm.js +0 -96
  78. package/dist/assets/ErrorBoundaryDoc-DoaAg68p.js +0 -111
  79. package/dist/assets/ExampleActionPlanPage-C0fIMZCD.js +0 -1
  80. package/dist/assets/ExampleAppDoc-DzIU81Fn.js +0 -1
  81. package/dist/assets/ExampleCard-DuLrb3t-.js +0 -1
  82. package/dist/assets/ExampleCrudReportsPage-M0pz6tdM.js +0 -1
  83. package/dist/assets/ExampleDashboardPage-CRG5r3Vw.js +0 -1
  84. package/dist/assets/ExampleIdeasPage-I84ZMLY4.js +0 -1
  85. package/dist/assets/ExampleImportWizardPage-h4YqrrSe.js +0 -1
  86. package/dist/assets/ExampleSettingsPage-CwdWqoaP.js +0 -1
  87. package/dist/assets/FileUploadDoc-9-UujFNX.js +0 -34
  88. package/dist/assets/FilterBar-DDTqqUfZ.js +0 -1
  89. package/dist/assets/FormDoc-CVES6n3d.js +0 -81
  90. package/dist/assets/FoundationOverview-DT0u11Gz.js +0 -1
  91. package/dist/assets/GridDoc-CbHFSILF.js +0 -28
  92. package/dist/assets/HooksDoc-Ctxdk6Wq.js +0 -665
  93. package/dist/assets/HoverCardDoc-8Wkaafdj.js +0 -31
  94. package/dist/assets/I18nDoc-D3Q2m7ik.js +0 -167
  95. package/dist/assets/IconPickerDoc-DZ26Gdpg.js +0 -10
  96. package/dist/assets/IconsFoundationDoc-xOxtC7CW.js +0 -33
  97. package/dist/assets/InputDoc-BhztAiuJ.js +0 -211
  98. package/dist/assets/LabelDoc-A4hmTRRV.js +0 -42
  99. package/dist/assets/LeadershipDoc-CqOSfWsP.js +0 -452
  100. package/dist/assets/MediaDoc-C78gvC8p.js +0 -459
  101. package/dist/assets/MenubarDoc-DCnmd2tO.js +0 -165
  102. package/dist/assets/ModuleAccessDoc-CmD5nHDp.js +0 -153
  103. package/dist/assets/ModulesDialogDoc-DVit1CA-.js +0 -46
  104. package/dist/assets/MultiselectPermissionsDoc-tlJMs04L.js +0 -34
  105. package/dist/assets/NavigationMenuDoc-q1fbc89j.js +0 -116
  106. package/dist/assets/OnboardingDialogDoc-3A3eBYrq.js +0 -55
  107. package/dist/assets/PaginationDoc-B8-bMz5J.js +0 -27
  108. package/dist/assets/PaginationDoc-BkGdxHL3.js +0 -98
  109. package/dist/assets/PlacesDoc-CKPO6ATs.js +0 -226
  110. package/dist/assets/PopoverDoc-CJPU4Ags.js +0 -64
  111. package/dist/assets/ProgressDoc-CpjbTL4o.js +0 -29
  112. package/dist/assets/QualiexUserFieldDoc-DDwumlRw.js +0 -149
  113. package/dist/assets/RadioGroupDoc-D6tSZz8G.js +0 -57
  114. package/dist/assets/RadiusDoc-B4xSnajw.js +0 -7
  115. package/dist/assets/ReportRequestListDoc-C0LIaU8P.js +0 -15
  116. package/dist/assets/RequiredFieldsCounterDoc-COesoSdx.js +0 -58
  117. package/dist/assets/ResizableDoc-CW0-XQuB.js +0 -104
  118. package/dist/assets/RichTextEditorDoc-C8c_XA9P.js +0 -24
  119. package/dist/assets/ScrollAreaDoc-BxtoAPaZ.js +0 -28
  120. package/dist/assets/SecurityDoc-wOVqpg2F.js +0 -204
  121. package/dist/assets/SelectDoc-C75gtY9D.js +0 -80
  122. package/dist/assets/SeparatorDoc-BjQBPB1P.js +0 -4
  123. package/dist/assets/ServicesDoc-CXTctwBl.js +0 -308
  124. package/dist/assets/ShadowsDoc-C6Lw8_x2.js +0 -9
  125. package/dist/assets/SignDoc-Bh5ZUg5x.js +0 -66
  126. package/dist/assets/SkeletonDoc-rTLGK5VE.js +0 -54
  127. package/dist/assets/SliderDoc-JMAMDub7.js +0 -41
  128. package/dist/assets/SpacingDoc-RljOrpwA.js +0 -12
  129. package/dist/assets/SplitButtonDoc-CvShUW3w.js +0 -53
  130. package/dist/assets/StepSelectorDoc-C-nAap9H.js +0 -41
  131. package/dist/assets/SwitchDoc-DLnqmkPr.js +0 -56
  132. package/dist/assets/TableDoc-B8EpWLVg.js +0 -128
  133. package/dist/assets/TabsDoc-DIBtl_uC.js +0 -42
  134. package/dist/assets/TeamSelectorDoc-B7OnCbL7.js +0 -10
  135. package/dist/assets/TermsOfUseDoc-Bb-pw08s.js +0 -16
  136. package/dist/assets/TextareaDoc-DGnqMqEC.js +0 -46
  137. package/dist/assets/ToastDoc-DjYyc7ae.js +0 -157
  138. package/dist/assets/ToggleDoc-C9ZOVjkY.js +0 -51
  139. package/dist/assets/TooltipDoc-BEx4l9-i.js +0 -58
  140. package/dist/assets/TruncatedCellDoc-BbV1bRSY.js +0 -12
  141. package/dist/assets/TypographyFoundationDoc-CUDYjRo9.js +0 -7
  142. package/dist/assets/UpdatesNotificationDoc-7nyjzLMJ.js +0 -29
  143. package/dist/assets/UsersGroupsSelectorDoc-C0KlTAL5.js +0 -18
  144. package/dist/assets/UtilitiesDoc-DGxaHVV1.js +0 -145
  145. package/dist/assets/ViewerDialogsDoc-CnTPTEz0.js +0 -1
  146. package/dist/assets/blocks-B6LrJeAM.js +0 -1
  147. package/dist/assets/building-DeVappnD.js +0 -1
  148. package/dist/assets/calendar-days-BQ0na5kM.js +0 -1
  149. package/dist/assets/check-check-C_-PJCJa.js +0 -1
  150. package/dist/assets/circle-plus-CpIcep-O.js +0 -1
  151. package/dist/assets/circle-x-jPpBPew0.js +0 -1
  152. package/dist/assets/clipboard-list-CXNPdciZ.js +0 -1
  153. package/dist/assets/cloud-upload-BEjzumjl.js +0 -1
  154. package/dist/assets/crown-CqNsQIsm.js +0 -1
  155. package/dist/assets/date-picker-BW3eGOe_.js +0 -1
  156. package/dist/assets/disabled-menu-item-C2YaMvSt.js +0 -1
  157. package/dist/assets/drawer-D5rflIcD.js +0 -3
  158. package/dist/assets/file-braces-DFb5X9so.js +0 -1
  159. package/dist/assets/file-pen-line-CyUGKkEN.js +0 -1
  160. package/dist/assets/git-branch-BcXv9mpp.js +0 -1
  161. package/dist/assets/globe-CpMIWAcv.js +0 -1
  162. package/dist/assets/hash-cQWdKjya.js +0 -1
  163. package/dist/assets/hourglass-BahQ3eDv.js +0 -1
  164. package/dist/assets/hover-card-R66N85sZ.js +0 -1
  165. package/dist/assets/iframe-dialog-V0mW5aBb.js +0 -1
  166. package/dist/assets/index-DkiftrvI.js +0 -352
  167. package/dist/assets/index-nmBjO9Th.css +0 -1
  168. package/dist/assets/life-buoy-ByXiPddz.js +0 -1
  169. package/dist/assets/loading-state-Cb5_t5uE.js +0 -1
  170. package/dist/assets/lucide-react-Cp3Yw3Zm.js +0 -1
  171. package/dist/assets/package-B3-pVvPM.js +0 -1
  172. package/dist/assets/pen-Bi_lmmKT.js +0 -1
  173. package/dist/assets/pin-DVsSl8QA.js +0 -1
  174. package/dist/assets/printer-BnJ8B6m-.js +0 -1
  175. package/dist/assets/radio-group-BHAaNGsm.js +0 -1
  176. package/dist/assets/server-CtzFTfKR.js +0 -1
  177. package/dist/assets/share-2-Dv8Do445.js +0 -1
  178. package/dist/assets/shield-check-CFXjOV_w.js +0 -1
  179. package/dist/assets/shield-x-DJTRfVux.js +0 -1
  180. package/dist/assets/slider-v9tXBSnB.js +0 -1
  181. package/dist/assets/smartphone-BSNR60L7.js +0 -1
  182. package/dist/assets/step-selector-ATTh_9Wa.js +0 -1
  183. package/dist/assets/text-align-start-qE-MbYYw.js +0 -1
  184. package/dist/assets/thumbs-up-D_XIW_uX.js +0 -1
  185. package/dist/assets/trash-DTWQwpwA.js +0 -1
  186. package/dist/assets/trending-up-jip5-leJ.js +0 -1
  187. package/dist/assets/useMockCrud-CN4vjyOZ.js +0 -1
  188. package/dist/assets/user-check-BlH3EDWK.js +0 -1
  189. package/dist/assets/user-plus-BqwXwD-c.js +0 -1
  190. package/dist/index.html +0 -33
@@ -1,189 +0,0 @@
1
- import{j as e,a,b as t,c as r,d as s,a4 as l,A as n,B as c,ei as m,bs as u}from"./index-DkiftrvI.js";import{C as x}from"./ComponentDocTemplate-CQbBhfvZ.js";import{C as p}from"./circle-x-jPpBPew0.js";import"./ExampleCard-DuLrb3t-.js";function h(){return e.jsxs("div",{className:"space-y-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Rota Raiz e Catch-All"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["A rota ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"/"})," ",e.jsx("strong",{children:"não"})," corresponde ao padrão ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"/:alias/*"}),", portanto o ",e.jsx("code",{children:"AliasRouteGuard"}),' nunca é executado. É obrigatório adicionar um redirect programático para evitar que a página fique presa em "Redirecionando...".']}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-destructive",children:"❌ Errado — Texto estático"})}),e.jsxs(s,{children:[e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`// Nunca redireciona — fica preso para sempre
2
- <Route path="*" element={
3
- <div>Redirecionando...</div>
4
- } />`}),e.jsx("p",{className:"text-xs text-muted-foreground mt-2",children:'Texto estático não executa navegação. O usuário vê "Redirecionando..." indefinidamente.'})]})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-green-600 dark:text-green-400",children:"✅ Correto — Navigate programático"})}),e.jsx(s,{children:e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`// Redireciona para /:alias/defaultPath
5
- <Route path="/" element={
6
- <ProtectedRoute>
7
- <RootRedirect />
8
- </ProtectedRoute>
9
- } />
10
-
11
- // Catch-all para rotas inválidas
12
- <Route path="*" element={
13
- <CatchAllRedirect />
14
- } />`})})]})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-base",children:"Implementação"})}),e.jsxs(s,{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2",children:"RootRedirect"}),e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`function RootRedirect() {
15
- const { alias } = useAuth();
16
- if (!alias) return null; // ProtectedRoute garante auth
17
- return <Navigate to={\`/\${alias}/i\`} replace />;
18
- }`})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2",children:"CatchAllRedirect"}),e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`function CatchAllRedirect() {
19
- const { alias, isAuthenticated } = useAuth();
20
- if (isAuthenticated && alias) {
21
- return <Navigate to={\`/\${alias}/i\`} replace />;
22
- }
23
- return <Navigate to="/login" replace />;
24
- }`})]})]})]})]})}function g(){return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2 flex items-center gap-2",children:[e.jsx(l,{className:"h-5 w-5 text-yellow-500"}),"ProtectedRoute — Regra Crítica"]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["O ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"ProtectedRoute"})," ",e.jsx("strong",{children:"não deve"})," exibir loading quando o usuário já está autenticado. Se o loading aparecer durante o ",e.jsx("code",{children:"switchUnit()"}),", o ",e.jsx("code",{children:"AliasRouteGuard"})," é desmontado, perdendo o estado interno do ",e.jsx("code",{children:"prevActiveAliasRef"})," e causando reversão da troca de unidade."]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-destructive",children:"❌ Errado"})}),e.jsxs(s,{children:[e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`// Desmonta o guard durante switchUnit!
25
- if (isLoading) {
26
- return <Loading />;
27
- }`}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:[e.jsx("code",{children:"isLoading"})," fica ",e.jsx("code",{children:"true"})," durante ",e.jsx("code",{children:"switchUnit()"}),", desmontando o ",e.jsx("code",{children:"AliasRouteGuard"})," e seu ",e.jsx("code",{children:"prevActiveAliasRef"}),"."]})]})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-green-600 dark:text-green-400",children:"✅ Correto"})}),e.jsxs(s,{children:[e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`// Loading só na inicialização
28
- if (isLoading && !isAuthenticated) {
29
- return <Loading />;
30
- }`}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:["O loading só aparece quando o usuário ainda não autenticou. Durante ",e.jsx("code",{children:"switchUnit()"}),", o guard permanece montado."]})]})]})]})]})}const j=[{title:"Alias ausente",icon:l,color:"text-yellow-500",badge:"redirect",badgeVariant:"outline",description:"URL sem alias → redireciona para /{aliasAtivo}/{path}",example:"/documents → /empresa-a/documents"},{title:"Alias diferente",icon:m,color:"text-blue-500",badge:"switchUnit",badgeVariant:"secondary",description:"Alias na URL ≠ ativo → Guard chama switchUnit() para sincronizar sessão com URL",example:"/empresa-b/documents (ativo: empresa-a) → switchUnit(empresa-b)"},{title:"Alias correto",icon:u,color:"text-green-500",badge:"render",badgeVariant:"default",description:"Alias coincide com o ativo → renderiza children",example:"/empresa-a/documents ✓"},{title:"Alias inválido",icon:p,color:"text-destructive",badge:"fallback",badgeVariant:"danger",description:"Alias não existe nas companies → redireciona para alias padrão",example:"/xyz-inexistente/documents → /empresa-a/documents"}];function f(){return e.jsxs("div",{className:"space-y-6",children:[e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-base",children:"Arquitetura: URL como Fonte Única de Verdade"})}),e.jsxs(s,{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3 text-sm flex-wrap",children:[e.jsx("span",{className:"font-mono bg-muted/50 rounded px-2 py-1",children:"Seletor/Header"}),e.jsx(n,{className:"h-4 w-4 text-muted-foreground"}),e.jsxs("span",{className:"font-mono bg-muted/50 rounded px-2 py-1",children:["navigate(/","{alias}",")"]}),e.jsx(n,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("span",{className:"font-mono bg-muted/50 rounded px-2 py-1 text-yellow-600 dark:text-yellow-400",children:"URL muda"}),e.jsx(n,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("span",{className:"font-mono bg-muted/50 rounded px-2 py-1 text-primary",children:"Guard → switchUnit()"})]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["O header ",e.jsx("strong",{children:"nunca"})," chama ",e.jsx("code",{children:"switchUnit"})," diretamente. Ele apenas navega para a URL com o novo alias. O ",e.jsx("code",{children:"AliasRouteGuard"})," detecta a mudança e sincroniza a sessão. Isso elimina race conditions entre dois writers concorrentes."]})]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:j.map(i=>e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsxs(r,{className:"flex items-center gap-2 text-base",children:[e.jsx(i.icon,{className:`h-5 w-5 ${i.color}`}),i.title,e.jsx(c,{variant:i.badgeVariant,className:"ml-auto text-xs",children:i.badge})]})}),e.jsxs(s,{className:"space-y-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:i.description}),e.jsx("div",{className:"flex items-center gap-2 text-xs font-mono bg-muted/50 rounded px-3 py-2",children:e.jsx("span",{children:i.example})})]})]},i.title))})]})}function b(){const i=[{scenario:"URL sem alias",url:"/documents",action:"navigate(/{alias}/documents, replace)",result:"Redirect automático"},{scenario:"Alias ≠ ativo",url:"/empresa-b/docs",action:"switchUnit(empresa-b)",result:"Guard sincroniza sessão"},{scenario:"Troca via seletor",url:"/empresa-a/docs",action:"Header navega → URL muda → Guard switchUnit()",result:"Sessão segue URL"},{scenario:"Alias = ativo",url:"/empresa-a/docs",action:"Nenhuma",result:"Renderiza children"},{scenario:"Alias inexistente",url:"/xyz/docs",action:"navigate(/{aliasDefault}/docs, replace)",result:"Fallback para alias ativo"}];return e.jsxs("div",{className:"space-y-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Tabela de Comportamento"}),e.jsx("div",{className:"rounded-lg border overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b bg-muted/50",children:[e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Cenário"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"URL"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Ação do Guard"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Resultado"})]})}),e.jsx("tbody",{children:i.map((o,d)=>e.jsxs("tr",{className:"border-b last:border-0",children:[e.jsx("td",{className:"px-4 py-3 text-sm font-medium",children:o.scenario}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:o.url}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:o.action}),e.jsx("td",{className:"px-4 py-3 text-sm",children:o.result})]},d))})]})})]})}function N(){const i=[{group:"Saber Gestão",name:"Competências",url:"https://competencias.sabergestao.com.br/{alias}",strategy:"/{alias} no path"},{group:"Saber Gestão",name:"Desempenho",url:"https://desempenho.sabergestao.com.br/{alias}",strategy:"/{alias} no path"},{group:"Saber Gestão",name:"Educação",url:"https://educacao.sabergestao.com.br/{alias}",strategy:"/{alias} no path"},{group:"Saber Gestão",name:"PDI",url:"https://pdi.sabergestao.com.br/{alias}",strategy:"/{alias} no path"},{group:"Saber Gestão",name:"Pulso",url:"https://nr1pulso.sabergestao.com.br/{alias}",strategy:"/{alias} no path"},{group:"Saber Gestão",name:"Treinamentos",url:"https://treinamentos.sabergestao.com.br/{alias}",strategy:"/{alias} no path"},{group:"Qualiex",name:"OKR",url:"https://okr.qualiex.com/{alias}",strategy:"/{alias} no path"},{group:"Clássicos (v1)",name:"Docs, ISO, Ocorrências...",url:"https://docs.qualiex.com/...",strategy:"Sem alias (v1)"}];return e.jsxs("div",{className:"space-y-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"URLs por Módulo"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Módulos Saber Gestão e OKR usam ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"buildModuleUrl"})," para injetar o alias. Módulos clássicos (v1) não recebem alias no path."]}),e.jsx("div",{className:"rounded-lg border overflow-x-auto",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b bg-muted/50",children:[e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Grupo"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Módulo"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Template da URL"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Estratégia"})]})}),e.jsx("tbody",{children:i.map((o,d)=>e.jsxs("tr",{className:"border-b last:border-0",children:[e.jsx("td",{className:"px-4 py-3 text-sm font-medium",children:o.group}),e.jsx("td",{className:"px-4 py-3 text-sm",children:o.name}),e.jsx("td",{className:"px-4 py-3 font-mono text-xs text-muted-foreground",children:o.url}),e.jsx("td",{className:"px-4 py-3 text-sm",children:e.jsx(c,{variant:o.strategy.includes("path")?"default":"outline",className:"text-xs",children:o.strategy})})]},d))})]})})]})}function R(){const i=["Atualizar forlogic-core para a versão mais recente","Importar AliasRouteGuard de forlogic-core","Envolver as rotas com /:alias como prefixo","Colocar AliasRouteGuard dentro de ProtectedRoute","Adicionar rota / com RootRedirect dentro de ProtectedRoute","Adicionar rota catch-all /* com CatchAllRedirect (Navigate programático)","Garantir que ProtectedRoute use isLoading && !isAuthenticated no loading","Testar: acessar URL sem alias deve redirecionar","Testar: acessar URL com alias diferente deve trocar unidade","Testar: troca via seletor deve atualizar URL"];return e.jsxs("div",{className:"space-y-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Guia de Migração"}),e.jsx(a,{children:e.jsx(s,{className:"pt-6",children:e.jsx("ol",{className:"space-y-3",children:i.map((o,d)=>e.jsxs("li",{className:"flex items-start gap-3 text-sm",children:[e.jsx("span",{className:"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground text-xs font-medium",children:d+1}),e.jsx("span",{className:"pt-0.5",children:o})]},d))})})})]})}function v(){return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2 flex items-center gap-2",children:[e.jsx(l,{className:"h-5 w-5 text-yellow-500"}),"Pitfall — Navegação Interna sem Alias"]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Ao usar ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"navigate()"})," ou paths hardcoded dentro de componentes protegidos pelo ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"AliasRouteGuard"}),", o primeiro segmento da URL é interpretado como alias. Se o path não incluir o alias, o guard redireciona para o alias padrão."]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-destructive",children:"❌ Errado"})}),e.jsx(s,{children:e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`// Path hardcoded sem alias
31
- navigate('/a/u');
32
- navigate('/a/c');
33
-
34
- // O guard interpreta "a" como alias
35
- // → alias inválido → redireciona para /{alias}/i`})})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-green-600 dark:text-green-400",children:"✅ Correto"})}),e.jsx(s,{children:e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`const { alias } = useAuth();
36
-
37
- // Prefixar com alias ativo
38
- navigate(\`/\${alias}/a/u\`);
39
- navigate(\`/\${alias}/a/c\`);
40
-
41
- // O guard reconhece o alias válido
42
- // → renderiza normalmente`})})]})]}),e.jsx(a,{children:e.jsx(s,{className:"pt-6",children:e.jsxs("p",{className:"text-sm",children:[e.jsx("strong",{children:"Regra:"})," Toda navegação interna (tabs, links, botões) em rotas protegidas pelo ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"AliasRouteGuard"})," deve usar ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"`/${alias}/path`"})," obtendo o alias via ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"useAuth()"}),"."]})})})]})}function L(){return e.jsxs(x,{title:"Alias via URL",description:"Sincronização bidirecional entre o alias (unidade/empresa) ativo na sessão e a URL do navegador. Garante que o alias esteja sempre presente na URL e que trocas de unidade sejam refletidas automaticamente.",component:e.jsx(f,{}),usage:`import { AliasRouteGuard } from 'forlogic-core';
43
- import { ProtectedRoute } from 'forlogic-core';
44
-
45
- // No App.tsx — todas as rotas sob /:alias
46
- <Route element={
47
- <ProtectedRoute>
48
- <AliasRouteGuard>
49
- <Outlet />
50
- </AliasRouteGuard>
51
- </ProtectedRoute>
52
- }>
53
- <Route path="/:alias/documents" element={<DocumentsPage />} />
54
- <Route path="/:alias/documents/:id" element={<DocumentDetailPage />} />
55
- <Route path="/:alias/settings" element={<SettingsPage />} />
56
-
57
- {/* Catch-all: redireciona rotas sem alias */}
58
- <Route path="/*" element={<AliasRedirect />} />
59
- </Route>`,installation:"import { AliasRouteGuard, useAliasFromUrl, buildModuleUrl } from 'forlogic-core';",examples:[{title:"Uso do useAliasFromUrl",description:"Hook para acessar o alias da URL e validá-lo contra as companies do usuário. Útil para lógica customizada.",preview:e.jsx(a,{children:e.jsx(s,{className:"pt-6",children:e.jsxs("div",{className:"space-y-3 font-mono text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"urlAlias"}),e.jsx("span",{children:'"empresa-a"'})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"isAliasMismatch"}),e.jsx("span",{children:"false"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"isValidAlias"}),e.jsx("span",{children:"true"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"isMissing"}),e.jsx("span",{children:"false"})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"matchedCompany"}),e.jsx("span",{children:"{ id, alias, name }"})]})]})})}),code:`import { useAliasFromUrl } from 'forlogic-core';
60
-
61
- function MyComponent() {
62
- const {
63
- urlAlias, // "empresa-a" | null
64
- isAliasMismatch, // true se alias da URL ≠ alias ativo
65
- isValidAlias, // true se alias existe nas companies
66
- isMissing, // true se não há alias na URL
67
- matchedCompany, // { id, alias, name } | null
68
- } = useAliasFromUrl();
69
-
70
- if (isMissing) return <p>Nenhum alias na URL</p>;
71
- if (!isValidAlias) return <p>Alias inválido</p>;
72
-
73
- return <p>Unidade: {matchedCompany?.name}</p>;
74
- }`},{title:"Antes / Depois (Migração)",description:"Como adaptar as rotas de um projeto consumidor existente.",preview:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-destructive",children:"❌ Antes"})}),e.jsx(s,{children:e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`<ProtectedRoute>
75
- <Route path="/documents" />
76
- <Route path="/settings" />
77
- </ProtectedRoute>`})})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-green-600 dark:text-green-400",children:"✅ Depois"})}),e.jsx(s,{children:e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto",children:`<ProtectedRoute>
78
- <AliasRouteGuard>
79
- <Route path="/:alias/documents" />
80
- <Route path="/:alias/settings" />
81
- <Route path="/*" element={<AliasRedirect />} />
82
- </AliasRouteGuard>
83
- </ProtectedRoute>`})})]})]}),code:`// Antes — sem alias na URL
84
- <Route element={<ProtectedRoute><Outlet /></ProtectedRoute>}>
85
- <Route path="/documents" element={<DocumentsPage />} />
86
- <Route path="/settings" element={<SettingsPage />} />
87
- </Route>
88
-
89
- // Depois — com alias na URL
90
- <Route element={
91
- <ProtectedRoute>
92
- <AliasRouteGuard>
93
- <Outlet />
94
- </AliasRouteGuard>
95
- </ProtectedRoute>
96
- }>
97
- <Route path="/:alias/documents" element={<DocumentsPage />} />
98
- <Route path="/:alias/settings" element={<SettingsPage />} />
99
- <Route path="/*" element={<AliasRedirect />} />
100
- </Route>`},{title:"buildModuleUrl — Navegação Inter-módulos",description:"Helper centralizado que substitui {alias} em templates de URL. Usado internamente pelo ModulesDialog e ModuleAccessGuard.",preview:e.jsx(a,{children:e.jsxs(s,{className:"pt-6 space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:"Entrada"}),e.jsx("div",{className:"font-mono text-sm bg-muted/50 rounded px-3 py-2",children:'buildModuleUrl("https://okr.qualiex.com/{alias}", "empresa-a")'})]}),e.jsx(n,{className:"h-4 w-4 text-muted-foreground mx-auto"}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:"Saída"}),e.jsx("div",{className:"font-mono text-sm bg-muted/50 rounded px-3 py-2 text-primary",children:"https://okr.qualiex.com/empresa-a"})]}),e.jsxs("div",{className:"border-t pt-3 space-y-1 text-xs text-muted-foreground",children:[e.jsx("p",{children:"• Sem alias → retorna a URL original sem alteração"}),e.jsx("p",{children:"• Substitui todas as ocorrências de {alias}"})]})]})}),code:`import { buildModuleUrl, handleExternalLink } from 'forlogic-core';
101
- import { useAuth } from 'forlogic-core';
102
-
103
- function MyComponent() {
104
- const { alias } = useAuth();
105
-
106
- // Uso direto
107
- const url = buildModuleUrl('https://okr.qualiex.com/{alias}', alias);
108
- // → "https://okr.qualiex.com/empresa-a"
109
-
110
- // Sem alias → retorna template original
111
- const fallback = buildModuleUrl('https://okr.qualiex.com/{alias}');
112
- // → "https://okr.qualiex.com/{alias}"
113
-
114
- // Com handleExternalLink
115
- const handleClick = () => {
116
- const moduleUrl = buildModuleUrl('https://competencias.sabergestao.com.br/{alias}', alias);
117
- handleExternalLink(moduleUrl);
118
- };
119
-
120
- return <button onClick={handleClick}>Abrir Competências</button>;
121
- }`},{title:"Fluxo Interno do Guard (Decisão Única + Concorrência)",description:'O guard usa 1 effect de decisão + 1 effect de tracking. O switchUnit usa "latest request wins" para evitar reversões.',preview:e.jsxs("div",{className:"space-y-4",children:[e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm",children:"Navegação via URL"})}),e.jsx(s,{children:e.jsxs("div",{className:"flex items-center gap-2 text-xs font-mono flex-wrap",children:[e.jsx("span",{className:"bg-muted/50 rounded px-2 py-1",children:"URL muda para /empresa-b"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-muted/50 rounded px-2 py-1",children:"prevRef = activeAlias (estável)"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-green-100 dark:bg-green-900/30 rounded px-2 py-1 text-green-700 dark:text-green-400",children:"switchUnit(empresa-b)"})]})})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm",children:"Troca via Seletor"})}),e.jsx(s,{children:e.jsxs("div",{className:"flex items-center gap-2 text-xs font-mono flex-wrap",children:[e.jsx("span",{className:"bg-muted/50 rounded px-2 py-1",children:"activeAlias muda"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-muted/50 rounded px-2 py-1",children:"prevRef ≠ activeAlias"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-primary/10 rounded px-2 py-1 text-primary",children:"URL sincroniza (sem switchUnit)"})]})})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-muted-foreground",children:"Ordem dos Effects (crítica)"})}),e.jsx(s,{children:e.jsxs("div",{className:"space-y-2 text-xs",children:[e.jsxs("div",{className:"flex items-center gap-2 font-mono",children:[e.jsx("span",{className:"bg-blue-100 dark:bg-blue-900/30 rounded px-2 py-1 text-blue-700 dark:text-blue-400",children:"Effect 1: Decisão"}),e.jsx("span",{className:"text-muted-foreground",children:"lê prevRef (valor anterior)"})]}),e.jsxs("div",{className:"flex items-center gap-2 font-mono",children:[e.jsx("span",{className:"bg-violet-100 dark:bg-violet-900/30 rounded px-2 py-1 text-violet-700 dark:text-violet-400",children:"Effect 2: Tracking"}),e.jsx("span",{className:"text-muted-foreground",children:"atualiza prevRef = activeAlias"})]}),e.jsxs("p",{className:"text-muted-foreground mt-1",children:["O effect de tracking é declarado ",e.jsx("strong",{children:"depois"})," do de decisão, garantindo que a decisão sempre lê o valor anterior do ref."]})]})})]}),e.jsxs(a,{children:[e.jsx(t,{className:"pb-2",children:e.jsx(r,{className:"text-sm text-muted-foreground",children:'Concorrência: "Latest Request Wins"'})}),e.jsxs(s,{children:[e.jsxs("div",{className:"flex items-center gap-2 text-xs font-mono flex-wrap",children:[e.jsx("span",{className:"bg-muted/50 rounded px-2 py-1",children:"Guard: switchUnit(A)"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-muted/50 rounded px-2 py-1",children:"Seletor: switchUnit(B)"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-red-100 dark:bg-red-900/30 rounded px-2 py-1 text-red-700 dark:text-red-400",children:"A abortado"}),e.jsx(n,{className:"h-3 w-3 text-muted-foreground"}),e.jsx("span",{className:"bg-green-100 dark:bg-green-900/30 rounded px-2 py-1 text-green-700 dark:text-green-400",children:"B efetivado"})]}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-2",children:["Cada ",e.jsx("code",{children:"switchUnit()"})," recebe um ",e.jsx("code",{children:"requestId"}),". Após cada ",e.jsx("code",{children:"await"}),", verifica se ainda é a requisição mais recente."]})]})]})]}),code:`// Guard: 1 effect de decisão + 1 effect de tracking
122
- useEffect(() => {
123
- // Case 1: missing → redirect
124
- // Case 2: invalid → redirect
125
- // Case 3: mismatch
126
- if (activeAlias !== prevActiveAliasRef.current) {
127
- // Sessão mudou via UI → sync URL
128
- navigate(buildAliasPath(activeAlias), { replace: true });
129
- } else {
130
- // URL mudou → switchUnit()
131
- switchUnit(matchedCompany);
132
- }
133
- }, [urlAlias, activeAlias, ...]);
134
-
135
- // DEPOIS do effect de decisão
136
- useEffect(() => {
137
- prevActiveAliasRef.current = activeAlias;
138
- }, [activeAlias]);
139
-
140
- // AuthContext: switchUnit com "latest request wins"
141
- const switchRequestIdRef = useRef(0);
142
-
143
- const switchUnit = useCallback(async (company) => {
144
- if (company.alias === authState.alias) return;
145
- const requestId = ++switchRequestIdRef.current;
146
-
147
- const token = await generateToken(...);
148
- if (switchRequestIdRef.current !== requestId) return;
149
-
150
- updateAuthState({ alias: newAlias, ... });
151
- }, [authState.alias, ...]);`},{title:"Estrutura Completa de Rotas (App.tsx)",description:"Exemplo completo mostrando a rota raiz com RootRedirect, rotas protegidas com AliasRouteGuard e catch-all com CatchAllRedirect.",preview:e.jsx(a,{children:e.jsx(s,{className:"pt-6",children:e.jsx("pre",{className:"text-xs font-mono bg-muted/50 rounded p-3 overflow-x-auto whitespace-pre-wrap",children:`<Routes>
152
- <Route path="/login" element={<LoginPage />} />
153
- <Route path="/callback" element={<CallbackPage />} />
154
-
155
- {/* Rota raiz — redireciona para /:alias/i */}
156
- <Route path="/" element={
157
- <ProtectedRoute><RootRedirect /></ProtectedRoute>
158
- } />
159
-
160
- {/* Rotas protegidas com alias */}
161
- <Route element={
162
- <ProtectedRoute>
163
- <AliasRouteGuard><Outlet /></AliasRouteGuard>
164
- </ProtectedRoute>
165
- }>
166
- <Route path="/:alias/dashboard" element={<DashboardPage />} />
167
- <Route path="/:alias/settings" element={<SettingsPage />} />
168
- </Route>
169
-
170
- {/* Catch-all — redireciona rotas inválidas */}
171
- <Route path="*" element={<CatchAllRedirect />} />
172
- </Routes>`})})}),code:`import { Navigate } from 'react-router-dom';
173
- import { useAuth } from 'forlogic-core';
174
-
175
- // Redireciona "/" para "/:alias/defaultPath"
176
- function RootRedirect() {
177
- const { alias } = useAuth();
178
- if (!alias) return null; // ProtectedRoute garante auth
179
- return <Navigate to={\`/\${alias}/i\`} replace />;
180
- }
181
-
182
- // Catch-all: redireciona rotas inválidas
183
- function CatchAllRedirect() {
184
- const { alias, isAuthenticated } = useAuth();
185
- if (isAuthenticated && alias) {
186
- return <Navigate to={\`/\${alias}/i\`} replace />;
187
- }
188
- return <Navigate to="/login" replace />;
189
- }`}],props:[{name:"children",type:"ReactNode",description:"Conteúdo protegido pelo guard (geralmente <Outlet />)"},{name:"paramName",type:"string",default:'"alias"',description:"Nome do param de rota do React Router (ex: :alias)"},{name:"urlAlias",type:"string | null",description:"(useAliasFromUrl) Alias extraído da URL"},{name:"isAliasMismatch",type:"boolean",description:"(useAliasFromUrl) true se alias da URL ≠ alias ativo na sessão"},{name:"isValidAlias",type:"boolean",description:"(useAliasFromUrl) true se o alias da URL existe nas companies do usuário"},{name:"isMissing",type:"boolean",description:"(useAliasFromUrl) true se não há alias na URL"},{name:"matchedCompany",type:"{ id, alias, name } | null",description:"(useAliasFromUrl) Company correspondente ao alias da URL"},{name:"urlTemplate",type:"string",description:"(buildModuleUrl) URL com placeholder {alias} para substituição"},{name:"alias",type:"string | undefined",description:"(buildModuleUrl) Alias a substituir no template. Se ausente, retorna a URL original"}],notes:["AliasRouteGuard deve ser usado DENTRO de ProtectedRoute, nunca fora — depende do contexto de autenticação.","O guard só age após isLoading=false e isAuthenticated=true — não interfere no fluxo de login.","switchUnit() já limpa o cache do React Query automaticamente — sem ação extra necessária.","Todos os redirects usam replace: true para não poluir o histórico do navegador.","URLs sem alias são redirecionadas automaticamente — links antigos continuam funcionando.","A navegação inter-módulos usa buildModuleUrl para substituir {alias} nas URLs dos módulos Saber Gestão e OKR.","Módulos clássicos (v1) não recebem alias no path — mantêm o comportamento original.","O guard usa 1 effect de decisão + 1 effect de tracking (declarado depois). A ordem garante que prevActiveAliasRef é lido antes de ser atualizado.","Troca via seletor: activeAlias muda → prevRef ≠ activeAlias → guard sincroniza URL (sem switchUnit). Troca via URL: activeAlias estável → prevRef = activeAlias → switchUnit().",'switchUnit() usa estratégia "latest request wins" com requestId: chamadas concorrentes são resolvidas — apenas a mais recente efetiva estado.',"switchUnit() faz short-circuit se company.alias === alias atual — evita processamento desnecessário.","switchUnit() NÃO usa setLoading() — manter authIsLoading=false durante a troca preserva a montagem do AliasRouteGuard.",'A rota / deve ter um redirect programático — texto estático como "Redirecionando..." não executa navegação.',"ProtectedRoute deve usar if (isLoading && !isAuthenticated) para não desmontar o guard durante switchUnit().","Navegação interna (tabs, links) em rotas com AliasRouteGuard DEVE usar /${alias}/path — paths hardcoded sem alias são interpretados incorretamente pelo guard."],hideToc:!1,children:[e.jsx(b,{}),e.jsx(N,{}),e.jsx(v,{}),e.jsx(h,{}),e.jsx(g,{}),e.jsx(R,{})]})}export{L as AliasUrlDoc};
@@ -1,74 +0,0 @@
1
- import{j as e,d7 as o,K as i,x as s,ei as a,aJ as u,P as d,ew as n,bk as l,a1 as c,r as x,B as p}from"./index-DkiftrvI.js";import{C as h}from"./ComponentDocTemplate-CQbBhfvZ.js";import"./ExampleCard-DuLrb3t-.js";function f(){const[t,r]=x.useState("");return e.jsx("div",{className:"w-full bg-background border rounded-lg",children:e.jsx("header",{className:"px-4 py-2",children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs("div",{className:"flex-shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("h1",{className:"text-lg font-semibold",children:"Usuários"}),e.jsx(p,{className:"bg-primary text-primary-foreground text-xs px-2 py-0.5",children:"Módulo"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Gerenciamento de usuários"})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-1 max-w-md",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(o,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4"}),e.jsx(i,{placeholder:"Buscar...",value:t,onChange:m=>r(m.target.value),className:"w-full pl-10 pr-8"}),t&&e.jsx(s,{variant:"ghost",size:"sm",className:"absolute right-1 top-1/2 transform -translate-y-1/2 h-6 w-6 p-0",onClick:()=>r(""),children:e.jsx(c,{className:"h-3.5 w-3.5"})})]}),e.jsx(s,{variant:"outline",size:"icon",className:"h-10 w-10",children:e.jsx(a,{className:"h-4 w-4"})})]}),e.jsxs("div",{className:"flex-shrink-0 ml-auto flex items-center gap-3",children:[e.jsxs(s,{size:"sm",children:[e.jsx(d,{className:"h-4 w-4 mr-1"}),"Novo"]}),e.jsx(s,{variant:"ghost",className:"h-auto p-2",children:e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsxs("div",{className:"text-left",children:[e.jsx("p",{className:"text-sm font-medium",children:"João Silva"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Empresa XYZ"})]}),e.jsx("div",{className:"w-8 h-8 bg-primary rounded-full flex items-center justify-center",children:e.jsx(n,{className:"h-4 w-4 text-primary-foreground"})}),e.jsx(l,{className:"h-4 w-4"})]})})]})]})})})}function g(){return e.jsxs("div",{className:"w-full",children:[e.jsxs("div",{className:"flex items-center justify-between h-14 px-4 border rounded-lg bg-background",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"bg-primary/10 text-primary px-2 py-1 rounded text-xs font-medium",children:"TÍTULO"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"←"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"→"}),e.jsx("div",{className:"bg-secondary/50 text-secondary-foreground px-2 py-1 rounded text-xs font-medium",children:"BUSCA"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"←"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:"→"}),e.jsx("div",{className:"bg-accent/50 text-accent-foreground px-2 py-1 rounded text-xs font-medium",children:"AÇÕES"}),e.jsx("div",{className:"bg-muted text-muted-foreground px-2 py-1 rounded text-xs font-medium",children:"PERFIL"})]})]}),e.jsx("p",{className:"text-xs text-muted-foreground text-center mt-2",children:"Diagrama das áreas internas do AppHeader (altura fixa: 56px)"})]})}function v(){return e.jsxs("div",{className:"flex gap-8 items-start",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium",children:'variant="dropdown"'}),e.jsx("div",{className:"border rounded-lg p-2 bg-background",children:e.jsx(s,{variant:"ghost",className:"h-auto p-2",children:e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsxs("div",{className:"text-left",children:[e.jsx("p",{className:"text-sm font-medium",children:"João Silva"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Empresa XYZ"})]}),e.jsx("div",{className:"w-8 h-8 bg-primary rounded-full flex items-center justify-center",children:e.jsx(n,{className:"h-4 w-4 text-primary-foreground"})}),e.jsx(l,{className:"h-4 w-4"})]})})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium",children:"Menu aberto"}),e.jsxs("div",{className:"border rounded-lg p-2 w-48 bg-background shadow-lg",children:[e.jsxs("div",{className:"py-1.5 px-2 hover:bg-muted rounded flex items-center gap-2 cursor-pointer",children:[e.jsx(a,{className:"h-4 w-4"}),e.jsx("span",{className:"text-sm",children:"Alterar Unidade"})]}),e.jsx("div",{className:"h-px bg-border my-1"}),e.jsxs("div",{className:"py-1.5 px-2 hover:bg-muted rounded flex items-center gap-2 cursor-pointer text-destructive",children:[e.jsx(c,{className:"h-4 w-4"}),e.jsx("span",{className:"text-sm",children:"Sair"})]})]})]})]})}function w(){return e.jsx(h,{title:"AppHeader",description:"Header principal da aplicação com título dinâmico, busca global integrada ao CRUD, ações customizáveis e informações do usuário. Altura fixa de 56px (h-14).",component:e.jsx(f,{}),usage:`import { AppLayout, usePageMetadata } from 'forlogic-core';
2
-
3
- // O AppHeader é renderizado automaticamente pelo AppLayout
4
- <AppLayout sidebarConfig={sidebarConfig}>
5
- <Routes>...</Routes>
6
- </AppLayout>
7
-
8
- // Para configurar título, subtítulo e breadcrumbs
9
- function UsersPage() {
10
- usePageMetadata({
11
- title: 'Usuários',
12
- subtitle: 'Gerenciamento de usuários do sistema'
13
- });
14
- }
15
-
16
- // Com breadcrumbs
17
- function EditUserPage() {
18
- usePageMetadata({
19
- title: 'Editar Usuário',
20
- subtitle: 'Atualize os dados cadastrais',
21
- breadcrumbs: [
22
- { label: 'Usuários', href: '/users' },
23
- { label: 'João Silva' }
24
- ]
25
- });
26
- }
27
-
28
- // Subtitle com ReactNode
29
- function DetailPage() {
30
- usePageMetadata({
31
- title: 'Detalhes',
32
- subtitle: <span>Veja a <Link to="/docs">documentação</Link></span>
33
- });
34
- }`,examples:[{title:"Estrutura do Componente",description:"O AppHeader possui 4 áreas internas: Título (esquerda), Busca (centro), Ações (direita) e Perfil (extrema direita).",preview:e.jsx(g,{}),code:`// Áreas do AppHeader
35
- // 1. Título: Título da página + Subtítulo + Badge do módulo
36
- // 2. Busca: Input de busca global (visível quando habilitado)
37
- // 3. Ações: Botões customizáveis via PageMetadataContext
38
- // 4. Perfil: UserInfo com dropdown de usuário
39
-
40
- // Altura fixa: 56px (h-14 no Tailwind)`},{title:"UserInfo Integrado",description:"Dropdown com informações do usuário, troca de unidade e logout.",preview:e.jsx(v,{}),code:`// UserInfo com variantes
41
- <UserInfo variant="dropdown" /> // No header
42
- <UserInfo variant="card" /> // Em páginas
43
-
44
- // Menu do usuário inclui:
45
- // - Alterar Unidade (submenu com todas unidades disponíveis)
46
- // - Sair (Logout)`},{title:"Busca Global",description:"Campo de busca com debounce sincronizado com URL (?search=termo).",preview:e.jsxs("div",{className:"flex items-center gap-2 max-w-md",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(o,{className:"absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground h-4 w-4"}),e.jsx(i,{placeholder:"Buscar...",className:"w-full pl-10 pr-8"})]}),e.jsx(s,{variant:"outline",size:"icon",className:"h-10 w-10",children:e.jsx(a,{className:"h-4 w-4"})})]}),code:`// Configurar campos pesquisáveis no service
47
- const userService = createSimpleService({
48
- tableName: 'users',
49
- schema: 'common',
50
- searchFields: ['name', 'email', 'department'],
51
- });
52
-
53
- // A busca é exibida quando isSearchVisible = true no AuthContext`},{title:"Ações Customizáveis",description:"Botões de ação configurados via PageMetadataContext.",preview:e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(s,{variant:"outline",size:"sm",children:[e.jsx(u,{className:"h-4 w-4 mr-1"}),"Exportar"]}),e.jsxs(s,{size:"sm",children:[e.jsx(d,{className:"h-4 w-4 mr-1"}),"Novo"]})]}),code:`// ✅ CORRETO: Apenas botões de ação
54
- setHeaderActions(
55
- <>
56
- <Button variant="outline" size="sm">
57
- <Download className="h-4 w-4 mr-1" />
58
- Exportar
59
- </Button>
60
- <Button size="sm">
61
- <Plus className="h-4 w-4 mr-1" />
62
- Novo
63
- </Button>
64
- </>
65
- );
66
-
67
- // ❌ INCORRETO: Formulário no header
68
- setHeaderActions(
69
- <form onSubmit={...}>
70
- <Input />
71
- <Select />
72
- <Button type="submit">Salvar</Button>
73
- </form>
74
- );`}],props:[{name:"actions",type:"ReactNode",description:"Botões de ação à direita do header (via PageMetadataContext)"},{name:"variant (UserInfo)",type:'"card" | "dropdown"',default:'"card"',description:"Estilo de exibição do UserInfo"},{name:"selectedUnit (UserInfo)",type:"Company | null",description:"Unidade selecionada"},{name:"onUnitChange (UserInfo)",type:"(unit: Company) => void",description:"Callback ao trocar unidade"}],accessibility:["Busca acessível via teclado (Tab para navegar, Escape para limpar)","UserInfo dropdown acessível via teclado","Botões de ação com foco visível (focus-visible)",'Título da página anunciado por leitores de tela (role="heading")',"Atalho de teclado para busca (/ ou Ctrl+K pode ser implementado)"],notes:["✅ Use PageMetadataContext para ações dinâmicas","✅ Mantenha título curto e descritivo (máx. 3 palavras)","✅ Use um único header por página","✅ Limpe ações no useEffect cleanup","✅ Use ícones do Lucide nos botões de ação","❌ Não adicione múltiplos headers na mesma página","❌ Não modifique a altura do header (fixo em 56px)","❌ Não coloque formulários complexos no header","❌ Não use mais de 3 botões de ação","❌ Não esconda o UserInfo em páginas autenticadas"]})}export{w as AppHeaderDoc};
@@ -1,221 +0,0 @@
1
- import{j as e,B as p,aP as I,x as m,P as u,dS as x,aQ as h,o as r,ab as n,e0 as G,aY as D,S as P,a8 as L,bk as R,F as C,dI as A,a_ as B,dL as H,f8 as E,f9 as l,fa as d,fb as c,r as b,gj as k,em as O,e3 as F,gk as _}from"./index-DkiftrvI.js";import{C as q}from"./ComponentDocTemplate-CQbBhfvZ.js";import{a as z,b as M,A as Q,P as V}from"./pin-DVsSl8QA.js";import"./ExampleCard-DuLrb3t-.js";const W=[{icon:x,label:"Visão geral"},{icon:O,label:"Showcase"},{icon:n,label:"Liderança"},{icon:F,label:"Locais"},{icon:P,label:"Gestão",children:[{icon:n,label:"Usuários"},{icon:L,label:"Permissões"}]},{icon:V,label:"Design System"}];function $(){const[a,i]=b.useState(!0),[o,g]=b.useState(!0),[N,f]=b.useState("Visão geral"),[T,U]=b.useState(["Gestão"]);return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx(m,{variant:a?"primary":"outline",size:"sm",onClick:()=>{i(!0),g(!0)},children:"Expandido"}),e.jsx(m,{variant:a?"outline":"primary",size:"sm",onClick:()=>{i(!1),g(!1)},children:"Colapsado"}),e.jsxs("span",{className:"text-xs text-muted-foreground ml-2",children:[o?e.jsx(z,{className:"inline h-3 w-3 mr-1"}):e.jsx(M,{className:"inline h-3 w-3 mr-1"}),o?"Pinada":"Despinada"]})]}),e.jsx(E,{children:e.jsx("div",{className:"relative inline-block",children:e.jsxs("div",{className:r("bg-background border border-border rounded-lg py-4 space-y-3 transition-all duration-300 overflow-visible relative",a?"w-64 px-3":"w-16 px-1.5"),children:[a?e.jsxs("div",{className:"flex items-center gap-2 pl-2 h-10",children:[e.jsx("button",{className:"flex-shrink-0 cursor-pointer",onClick:()=>{},children:e.jsx("img",{src:k.logo,alt:"Logo",className:"h-8 max-w-full object-contain",onError:s=>{s.target.src='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 24"%3E%3Ctext x="0" y="18" font-family="system-ui" font-size="16" font-weight="bold" fill="%23333"%3EForlogic%3C/text%3E%3C/svg%3E'}})}),e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsx("button",{className:"flex-1 min-w-0 text-sm font-medium truncate text-center cursor-pointer hover:text-accent-foreground transition-colors",onClick:()=>{},children:"Meu Módulo"})}),e.jsx(c,{side:"bottom",className:"max-w-[200px]",children:e.jsx("p",{children:"Meu Módulo"})})]})]}):e.jsx("div",{className:"flex flex-col items-center justify-center w-full",children:e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsx("button",{className:"flex items-center justify-center h-10 w-8 cursor-pointer",onClick:()=>{},children:e.jsx("img",{src:k.smallLogo,alt:"Logo",className:"h-6 w-auto object-contain",onError:s=>{s.target.src='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 34"%3E%3Crect width="34" height="34" rx="6" fill="%23e5e7eb"/%3E%3Ctext x="50%25" y="55%25" text-anchor="middle" font-family="system-ui" font-size="14" font-weight="bold" fill="%23333"%3EF%3C/text%3E%3C/svg%3E'}})})}),e.jsx(c,{side:"right",children:"Módulos"})]})}),e.jsxs("div",{className:"relative py-2",children:[e.jsx("div",{className:"border-t border-border"}),e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsx("button",{onClick:()=>{const s=!a;i(s),g(s)},className:r("absolute top-1/2 -translate-y-1/2 z-[100] h-6 w-6 flex items-center justify-center rounded-full bg-primary hover:bg-primary/90 shadow-md transition-colors",a?"-right-6":"-right-[18px]"),children:a?e.jsx(I,{className:"h-3.5 w-3.5 text-primary-foreground"}):e.jsx(h,{className:"h-3.5 w-3.5 text-primary-foreground"})})}),e.jsx(c,{side:"right",children:e.jsx("p",{children:a?"Recolher":"Expandir"})})]})]}),a?e.jsxs(m,{variant:"outline",className:"w-full gap-2 justify-start h-10",children:[e.jsx(u,{className:"h-4 w-4"}),"Novo Processo"]}):e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsx(m,{variant:"outline",size:"icon",className:"w-full h-10",children:e.jsx(u,{className:"h-4 w-4"})})}),e.jsx(c,{side:"right",children:"Novo Processo"})]}),e.jsx("div",{className:"space-y-1",children:W.map(s=>{const y=s.label===N,v="children"in s&&s.children,w=T.includes(s.label),S=()=>{U(t=>t.includes(s.label)?t.filter(j=>j!==s.label):[...t,s.label])};return a?v?e.jsxs("div",{children:[e.jsxs("div",{onClick:S,className:r("flex items-center justify-between h-10 px-3 rounded-md transition-colors cursor-pointer","hover:bg-muted text-foreground"),children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"flex items-center justify-center h-8 w-8",children:e.jsx(s.icon,{className:"h-4 w-4"})}),e.jsx("span",{className:"text-sm font-medium",children:s.label})]}),e.jsx(h,{className:r("h-4 w-4 transition-transform",w&&"rotate-90")})]}),w&&e.jsx("div",{className:"ml-6 mt-1 space-y-1 border-l border-border pl-3",children:s.children.map(t=>{const j=t.label===N;return e.jsxs("div",{onClick:()=>f(t.label),className:r("flex items-center gap-2 h-8 px-2 rounded-md transition-colors cursor-pointer text-sm",j?"bg-primary/10 text-primary font-medium":"text-muted-foreground hover:bg-muted hover:text-foreground"),children:[e.jsx(t.icon,{className:"h-3.5 w-3.5"}),e.jsx("span",{children:t.label})]},t.label)})})]},s.label):e.jsxs("div",{onClick:()=>f(s.label),className:r("flex items-center gap-3 h-10 px-3 rounded-md transition-colors cursor-pointer",y?"bg-primary/10 text-primary font-medium":"hover:bg-muted text-foreground"),children:[e.jsx("span",{className:"flex items-center justify-center h-8 w-8",children:e.jsx(s.icon,{className:"h-4 w-4"})}),e.jsx("span",{className:"text-sm",children:s.label})]},s.label):e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsx("div",{onClick:()=>{v?S():f(s.label)},className:r("flex items-center justify-center h-8 w-8 mx-auto rounded-md transition-colors cursor-pointer",y?"bg-primary/10 text-primary":"hover:bg-accent hover:text-accent-foreground"),children:e.jsx(s.icon,{className:"h-4 w-4"})})}),e.jsxs(c,{side:"right",children:[s.label,v&&" (expandir para ver subitens)"]})]},s.label)})}),a&&e.jsx("div",{className:"absolute inset-y-0 right-0 w-1 hover:bg-primary/20 transition-colors cursor-ew-resize"})]})})})]})}function X(){return e.jsxs("div",{className:"flex gap-8 items-start flex-wrap",children:[e.jsx("div",{className:"relative",children:e.jsxs("div",{className:"w-64 bg-background border border-border rounded-lg py-4 px-3 space-y-3 relative overflow-visible",children:[e.jsxs("div",{className:"flex items-center gap-2 px-2 py-2 border border-dashed border-primary/50 rounded relative",children:[e.jsx(p,{variant:"outline",className:"absolute -top-2.5 left-2 text-xs bg-background",children:"SidebarHeader"}),e.jsx("div",{className:"h-8 w-14 bg-muted rounded flex items-center justify-center text-[10px] flex-shrink-0",children:"Logo"}),e.jsx("span",{className:"text-[10px] truncate text-center flex-1",children:"appName"})]}),e.jsxs("div",{className:"relative py-2",children:[e.jsx("div",{className:"border-t border-dashed border-blue-500/50 relative",children:e.jsx(p,{variant:"outline",className:"absolute -top-2.5 right-0 text-[8px] bg-background text-blue-600 whitespace-nowrap",children:"Pin/Unpin"})}),e.jsx("div",{className:"absolute top-1/2 -translate-y-1/2 -right-5 h-5 w-5 rounded-full bg-primary flex items-center justify-center",children:e.jsx(I,{className:"h-2.5 w-2.5 text-primary-foreground"})})]}),e.jsxs("div",{className:"border border-dashed border-green-500/50 rounded p-2 relative",children:[e.jsx(p,{variant:"outline",className:"absolute -top-2.5 left-2 text-xs bg-background text-green-600",children:"SidebarActionTrigger"}),e.jsxs(m,{variant:"outline",size:"sm",className:"w-full gap-1 text-xs h-7 justify-start",children:[e.jsx(u,{className:"h-3 w-3"}),"Ação"]})]}),e.jsxs("div",{className:"border border-dashed border-orange-500/50 rounded p-2 relative space-y-1",children:[e.jsx(p,{variant:"outline",className:"absolute -top-2.5 left-2 text-xs bg-background text-orange-600",children:"NavigationItems"}),[{label:"Item simples",active:!0},{label:"Item com children",hasChildren:!0}].map((a,i)=>e.jsxs("div",{className:r("flex items-center justify-between px-2 py-1.5 rounded text-xs",a.active?"bg-primary/10 text-primary":"bg-muted/50"),children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(x,{className:"h-3 w-3"}),e.jsx("span",{children:a.label})]}),a.hasChildren&&e.jsx(h,{className:"h-3 w-3"})]},i))]}),e.jsx("div",{className:"absolute inset-y-0 right-0 w-1 border-r-2 border-dashed border-purple-400/50 rounded-r"}),e.jsx(p,{variant:"outline",className:"absolute top-1/2 -right-16 text-[8px] bg-background text-purple-600 whitespace-nowrap",children:"Resize rail"})]})}),e.jsxs("div",{className:"space-y-2 text-xs",children:[e.jsx("p",{className:"font-medium text-sm mb-3",children:"Hierarquia:"}),e.jsx("pre",{className:"bg-muted p-3 rounded text-xs font-mono leading-relaxed",children:`<Sidebar collapsible="icon">
2
- ├── SidebarHeader + Separator + Pin/Unpin button
3
- │ ├── Logo (clicável → abre ModulesDialog)
4
- │ └── appName (centralizado, clicável → abre ModulesDialog)
5
- │ └── Tooltip com nome completo ao hover
6
-
7
- │ Colapsado:
8
- │ └── SmallLogo (clicável → abre ModulesDialog)
9
- │ └── Tooltip com appName
10
-
11
- ├── SidebarActionTrigger (opcional, abaixo do separador)
12
- │ ├── variant='button' (padrão)
13
- │ │ ├── Ação única → executa direto
14
- │ │ └── Múltiplas → dropdown
15
- │ └── variant='split-button'
16
- │ ├── Primeira ação → botão principal
17
- │ └── Demais ações → dropdown
18
-
19
- └── SidebarContent
20
- └── NavigationItems
21
- ├── Item simples (Link)
22
- ├── Item com permissionCheck
23
- └── Item com children
24
- └── Collapsible > SidebarMenuSub`})]})]})}function K(){return e.jsx("div",{className:"flex gap-4 items-start flex-wrap",children:[{title:"Ativo",className:"bg-primary/10 text-primary font-medium",icon:x,label:"Início"},{title:"Hover",className:"bg-muted",icon:n,label:"Usuários"},{title:"Desabilitado",className:"opacity-50 cursor-not-allowed border",icon:G,label:"Admin"},{title:"Carregando",className:"opacity-50 border",icon:D,label:"Verificando...",spin:!0}].map(a=>e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:a.title}),e.jsxs("div",{className:r("flex items-center gap-3 px-3 py-2 rounded-md w-40",a.className),children:[e.jsx(a.icon,{className:r("h-4 w-4",a.spin&&"animate-spin")}),e.jsx("span",{className:"text-sm",children:a.label})]})]},a.title))})}function Y(){return e.jsxs("div",{className:"p-3 border rounded-md w-56 space-y-1 bg-background",children:[e.jsxs("div",{className:"flex items-center gap-3 h-10 px-3 rounded-md hover:bg-muted",children:[e.jsx("span",{className:"flex items-center justify-center h-8 w-8",children:e.jsx(x,{className:"h-4 w-4"})}),e.jsx("span",{className:"text-sm font-medium",children:"Início"})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between h-10 px-3 rounded-md hover:bg-muted cursor-pointer",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"flex items-center justify-center h-8 w-8",children:e.jsx(P,{className:"h-4 w-4"})}),e.jsx("span",{className:"text-sm font-medium",children:"Configurações"})]}),e.jsx(h,{className:"h-4 w-4 rotate-90"})]}),e.jsx("div",{className:"ml-6 mt-1 space-y-1 border-l border-border pl-3",children:[{icon:n,label:"Perfil",active:!0},{icon:L,label:"Segurança"}].map(a=>e.jsxs("div",{className:r("flex items-center gap-2 h-8 px-2 rounded-md text-sm",a.active?"bg-primary/10 text-primary font-medium":"text-muted-foreground hover:bg-muted"),children:[e.jsx(a.icon,{className:"h-3.5 w-3.5"}),e.jsx("span",{children:a.label})]},a.label))})]})]})}function J(){return e.jsxs("div",{className:"flex gap-6 items-start flex-wrap",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium text-center",children:"Uma Ação"}),e.jsxs("div",{className:"w-56 bg-background border rounded-lg p-3 space-y-3",children:[e.jsxs(m,{variant:"outline",className:"w-full gap-2 justify-start",children:[e.jsx(u,{className:"h-4 w-4"}),"Novo Processo"]}),e.jsx("div",{className:"border-t pt-2 space-y-1",children:[{icon:x,label:"Início",active:!0},{icon:n,label:"Usuários"}].map((a,i)=>e.jsxs("div",{className:r("flex items-center gap-3 px-3 py-2 rounded-md text-sm",a.active?"bg-primary/10 text-primary font-medium":"hover:bg-muted"),children:[e.jsx(a.icon,{className:"h-4 w-4"}),e.jsx("span",{children:a.label})]},i))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium text-center",children:"Múltiplas Ações"}),e.jsxs("div",{className:"w-56 bg-background border rounded-lg p-3 space-y-1",children:[e.jsxs(m,{variant:"outline",className:"w-full gap-2 justify-start",children:[e.jsx(u,{className:"h-4 w-4"}),"Criar",e.jsx(R,{className:"ml-auto h-4 w-4 rotate-180"})]}),e.jsx("div",{className:"border rounded-md bg-popover p-1 shadow-md",children:[{icon:C,label:"Novo Documento"},{icon:A,label:"Nova Pasta"},{icon:n,label:"Novo Grupo"}].map((a,i)=>e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 rounded-sm hover:bg-muted cursor-pointer",children:[e.jsx(a.icon,{className:"h-4 w-4"}),e.jsx("span",{className:"text-sm",children:a.label})]},i))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm font-medium text-center",children:"Split Button"}),e.jsxs("div",{className:"w-56 bg-background border rounded-lg p-3 space-y-3",children:[e.jsx(B,{label:"Novo Documento",onClick:()=>{},icon:C,variant:"outline",actions:[{id:"folder",label:"Nova Pasta",icon:A,onClick:()=>{}},{id:"group",label:"Novo Grupo",icon:n,onClick:()=>{}}],className:"w-full",menuAlign:"start"}),e.jsx("div",{className:"border-t pt-2 space-y-1",children:[{icon:x,label:"Início",active:!0},{icon:n,label:"Usuários"}].map((a,i)=>e.jsxs("div",{className:r("flex items-center gap-3 px-3 py-2 rounded-md text-sm",a.active?"bg-primary/10 text-primary font-medium":"hover:bg-muted"),children:[e.jsx(a.icon,{className:"h-4 w-4"}),e.jsx("span",{children:a.label})]},i))})]})]})]})}function Z(){return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3 p-3 border rounded-md bg-muted/30",children:[e.jsx(H,{className:"h-5 w-5 text-muted-foreground"}),e.jsxs("div",{className:"text-sm space-y-1",children:[e.jsx("p",{className:"font-medium",children:"Redimensionamento"}),e.jsxs("p",{className:"text-muted-foreground",children:["Quando ",e.jsx("code",{className:"bg-muted px-1 rounded text-xs",children:"resizable=true"}),", um rail aparece na borda direita. Arraste para redimensionar entre ",e.jsx("code",{className:"bg-muted px-1 rounded text-xs",children:"minWidth"})," e"," ",e.jsx("code",{className:"bg-muted px-1 rounded text-xs",children:"maxWidth"}),"."]}),e.jsxs("p",{className:"text-muted-foreground",children:["A largura é persistida automaticamente em ",e.jsx("code",{className:"bg-muted px-1 rounded text-xs",children:"localStorage"}),"."]})]})]}),e.jsx("pre",{className:"bg-muted p-3 rounded text-xs font-mono",children:`<AppSidebar
25
- config={sidebarConfig}
26
- resizable={true}
27
- minWidth={224} // padrão: 224px (14rem)
28
- maxWidth={384} // padrão: 384px (24rem)
29
- />`})]})}function ee(){return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex gap-4 items-start flex-wrap",children:[e.jsxs("div",{className:"p-3 border rounded-md space-y-2 w-64",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(z,{className:"h-4 w-4 text-primary"}),e.jsx("span",{className:"text-sm font-medium",children:"Pinada"})]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Sidebar permanece aberta. Estado salvo em ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"localStorage"}),"."]})]}),e.jsxs("div",{className:"p-3 border rounded-md space-y-2 w-64",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(M,{className:"h-4 w-4 text-muted-foreground"}),e.jsx("span",{className:"text-sm font-medium",children:"Despinada"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Sidebar inicia colapsada. Expande ao hover (desktop) ou toggle (mobile)."})]})]}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["O botão circular na borda do separador controla pin/unpin. Em telas ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"<768px"})," (mobile), o botão é ocultado."]})]})}function ae(){return e.jsx("div",{className:"space-y-3 w-full",children:[{badge:"Desktop ≥1024px",variant:"default",text:"Sidebar visível, pode ser pinada ou colapsar"},{badge:"Tablet 768-1023px",variant:"secondary",text:"Sidebar inicia colapsada, expande ao hover/click"},{badge:"Mobile <768px",variant:"outline",text:"Sidebar como drawer/sheet lateral (oculta por padrão)"}].map(a=>e.jsxs("div",{className:"flex gap-4 items-center",children:[e.jsx(p,{variant:a.variant,className:"shrink-0",children:a.badge}),e.jsx("span",{className:"text-sm text-muted-foreground",children:a.text})]},a.badge))})}function se(){const a=`https://${_().storageProjectId}.supabase.co/storage/v1/object/public/library-assets`,i=[{name:"Qualiex",flag:'VITE_IS_QUALIEX="true"',logo:`${a}/logo-qualiex.svg`,smallLogo:`${a}/small-forlogic.svg`,appName:"Plano de Controle"},{name:"Saber Gestão",flag:'VITE_IS_QUALIEX="false"',logo:`${a}/logo.svg`,smallLogo:`${a}/small.svg`,appName:"Plano de Controle"}];return e.jsx(E,{children:e.jsx("div",{className:"flex gap-8 items-start flex-wrap",children:i.map(o=>e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:o.name}),e.jsx("code",{className:"text-xs bg-muted px-1.5 py-0.5 rounded",children:o.flag})]}),e.jsxs("div",{className:"flex gap-4 items-start",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground text-center",children:"Expandido"}),e.jsx("div",{className:"w-64 bg-background border border-border rounded-lg py-4 px-3",children:e.jsxs("div",{className:"flex items-center gap-2 pl-2 h-10",children:[e.jsx("img",{src:o.logo,alt:`${o.name} Logo`,className:"h-8 max-w-[120px] object-contain flex-shrink-0"}),e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsxs("span",{className:"flex-1 min-w-0 text-sm font-medium text-center cursor-pointer hover:text-accent-foreground transition-colors inline-flex items-center justify-center gap-1 leading-tight py-1",children:[e.jsx("span",{className:"line-clamp-2",children:o.appName}),e.jsx(Q,{size:12,className:"flex-shrink-0 opacity-60"})]})}),e.jsx(c,{side:"bottom",className:"max-w-[200px]",children:e.jsx("p",{children:o.appName})})]})]})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground text-center",children:"Colapsado"}),e.jsx("div",{className:"w-16 bg-background border border-border rounded-lg py-4 px-1.5",children:e.jsx("div",{className:"flex flex-col items-center justify-center w-full",children:e.jsxs(l,{children:[e.jsx(d,{asChild:!0,children:e.jsx("button",{className:"flex items-center justify-center h-10 w-8 cursor-pointer",children:e.jsx("img",{src:o.smallLogo,alt:`${o.name} Small Logo`,className:"h-6 w-auto object-contain"})})}),e.jsx(c,{side:"right",children:e.jsx("p",{children:o.appName})})]})})})]})]})]},o.name))})})}function ne(){return e.jsxs(q,{title:"AppSidebar",description:"Sidebar de navegação principal da aplicação com suporte a pin/unpin, permissões assíncronas, ações de módulo (SidebarActionTrigger), redimensionamento e navegação hierárquica.",component:e.jsx($,{}),usage:`import { AppLayout } from 'forlogic-core';
30
- import type { SidebarConfig } from 'forlogic-core';
31
- import { Home, Users, Settings, Shield, Plus, FileText, Folder } from 'lucide-react';
32
-
33
- const sidebarConfig: SidebarConfig = {
34
- appName: 'Minha Aplicação',
35
-
36
- // Ações do módulo (opcional)
37
- moduleActions: {
38
- triggerLabel: 'Criar',
39
- triggerIcon: Plus,
40
- actions: [
41
- { id: 'new-doc', label: 'Novo Documento', icon: FileText, onClick: () => {} },
42
- { id: 'new-folder', label: 'Nova Pasta', icon: Folder, onClick: () => {} },
43
- ],
44
- },
45
-
46
- // Navegação (com suporte a hierarquia)
47
- navigation: [
48
- { label: 'Início', path: '/', icon: Home },
49
- { label: 'Usuários', path: '/users', icon: Users },
50
- {
51
- label: 'Configurações',
52
- path: '/settings',
53
- icon: Settings,
54
- children: [
55
- { label: 'Perfil', path: '/settings/profile', icon: Users },
56
- { label: 'Segurança', path: '/settings/security', icon: Shield },
57
- ],
58
- },
59
- ],
60
- };
61
-
62
- // Uso via AppLayout (recomendado)
63
- <AppLayout sidebarConfig={sidebarConfig}>
64
- <Routes>...</Routes>
65
- </AppLayout>
66
-
67
- // Uso direto (casos avançados)
68
- <AppSidebar
69
- config={sidebarConfig}
70
- resizable={true}
71
- minWidth={224}
72
- maxWidth={384}
73
- />`,tocItems:[{id:"tipos-typescript",label:"Tipos TypeScript"},{id:"componente-base",label:"Componente Base: Sidebar"}],examples:[{title:"Anatomia do Sidebar",description:"Estrutura hierárquica completa: Header, Actions, Separator com Pin, Navigation, e Resize rail.",preview:e.jsx(X,{}),code:`// Estrutura do AppSidebar
74
- <Sidebar collapsible="icon">
75
- ├── SidebarHeader (Logo + ModulesButton)
76
- ├── SidebarActionTrigger (ações de módulo)
77
- ├── Separator + Pin/Unpin button (borda)
78
- └── SidebarContent
79
- └── NavigationItems
80
- ├── Item simples (Link)
81
- ├── Item com permissionCheck
82
- └── Item com children (Collapsible)
83
- └── SidebarMenuSub`},{title:"Estados Visuais",description:"Itens de navegação possuem 4 estados: Ativo (bg-primary/10), Hover (bg-muted), Desabilitado (opacity-50 + Lock icon), e Carregando (spinner durante permissionCheck).",preview:e.jsx(K,{}),code:`// Matching de rota ativa (hierárquico)
84
- const isActive = (path: string) =>
85
- location.pathname === path ||
86
- location.pathname.startsWith(path + '/');
87
-
88
- // Item com verificação de permissão assíncrona
89
- {
90
- label: 'Gestão',
91
- path: '/management',
92
- icon: Settings,
93
- permissionCheck: async () => {
94
- return await checkUserPermission('management');
95
- }
96
- }
97
- // → Exibe Loader2 (spin) enquanto verifica
98
- // → Exibe Lock + "Acesso restrito" se false`},{title:"Navegação Hierárquica",description:"Suporte a itens com children (máximo 2 níveis). No modo expandido, usa Collapsible com ChevronRight. No modo colapsado, exibe tooltip.",preview:e.jsx(Y,{}),code:`const navigation: SidebarNavigationItem[] = [
99
- { label: 'Início', path: '/', icon: Home },
100
- {
101
- label: 'Configurações',
102
- path: '/settings',
103
- icon: Settings,
104
- children: [
105
- { label: 'Perfil', path: '/settings/profile', icon: Users },
106
- { label: 'Segurança', path: '/settings/security', icon: Shield },
107
- ],
108
- },
109
- ];`},{title:"Ações de Módulo (SidebarActionTrigger)",description:'Suporta duas variantes: "button" (padrão) com ação direta ou dropdown, e "split-button" com ação principal + dropdown de ações secundárias. No modo colapsado, ambas exibem ícone com tooltip.',preview:e.jsx(J,{}),code:`// variant='button' (padrão) — ação única ou dropdown
110
- moduleActions: {
111
- triggerLabel: 'Criar',
112
- triggerIcon: Plus,
113
- actions: [
114
- { id: 'new-doc', label: 'Novo Documento', icon: FileText, onClick: handleNewDoc },
115
- { id: 'new-folder', label: 'Nova Pasta', icon: Folder, onClick: handleNewFolder },
116
- ],
117
- }
118
-
119
- // variant='split-button' — primeira ação = botão principal, demais = dropdown
120
- moduleActions: {
121
- variant: 'split-button',
122
- actions: [
123
- { id: 'new-doc', label: 'Novo Documento', icon: FileText, onClick: handleNewDoc },
124
- { id: 'new-folder', label: 'Nova Pasta', icon: Folder, onClick: handleNewFolder },
125
- { id: 'import', label: 'Importar', icon: Upload, onClick: handleImport },
126
- ],
127
- }`},{title:"Pin / Unpin",description:"O botão circular na borda do separador controla se a sidebar permanece aberta (pinada) ou colapsa automaticamente.",preview:e.jsx(ee,{}),code:`// Internamente o AppSidebar usa:
128
- import { getSidebarPinnedPreference, setSidebarPinnedPreference }
129
- from './sidebar-utils';
130
-
131
- // Persistência em localStorage ('forlogic-sidebar-pinned')
132
- // Botão circular usa bg-primary com ChevronLeft/Right
133
- // Oculto em mobile (hidden md:block)`},{title:"Redimensionamento",description:"Quando resizable=true, um rail aparece na borda direita para arrastar. A largura é persistida em localStorage.",preview:e.jsx(Z,{}),code:`// useSidebarResize hook
134
- import { useSidebarResize } from 'forlogic-core';
135
-
136
- const resize = useSidebarResize({
137
- minWidth: 224, // Mínimo (14rem)
138
- maxWidth: 384, // Máximo (24rem)
139
- defaultWidth: 240, // Padrão (15rem)
140
- storageKey: 'app-sidebar-width',
141
- isOpen: true,
142
- onResize: (width) => console.log(width),
143
- });
144
-
145
- // resize.width, resize.isDragging,
146
- // resize.dragRef, resize.handleMouseDown`},{title:"Comportamento Responsivo",description:"A sidebar adapta-se automaticamente ao tamanho da tela.",preview:e.jsx(ae,{}),code:`// O AppSidebar usa collapsible="icon"
147
- // Em desktop: colapsa para 16px (ícones apenas)
148
- // Em mobile: comportamento de drawer
149
-
150
- // useSidebar() hook disponível para controle externo
151
- import { useSidebar } from 'forlogic-core';
152
-
153
- const { open, setOpen, state, toggleSidebar } = useSidebar();
154
- // state: "expanded" | "collapsed"`},{title:"Branding: Qualiex vs Saber Gestão",description:"O logo e ícone da sidebar mudam conforme a variável de ambiente VITE_IS_QUALIEX. O logo é clicável e abre o ModulesDialog. O appName aparece centralizado ao lado do logo com tooltip para nomes longos.",preview:e.jsx(se,{}),code:`// lib/assets/index.ts — seleção automática de logo
155
- import { LOGO_CONFIG } from '../config';
156
-
157
- export const assets = {
158
- logo: LOGO_CONFIG.isQualiex ? qualiexLogo : saberLogo,
159
- smallLogo: LOGO_CONFIG.isQualiex ? qualiexSmall : saberSmall,
160
- };
161
-
162
- // .env
163
- VITE_IS_QUALIEX="true" // → Logo Qualiex
164
- VITE_IS_QUALIEX="false" // → Logo Saber Gestão
165
-
166
- // SidebarHeader — layout atual:
167
- // Expandido: [Logo] [appName centralizado] — ambos clicáveis
168
- // Colapsado: [SmallLogo com tooltip] — clicável`}],props:[{name:"config",type:"SidebarConfig",description:"Configuração principal: appName, navigation[], moduleActions"},{name:"config.appName",type:"string",description:"Nome exibido centralizado ao lado do logo (expandido) ou no tooltip do logo (colapsado). Clicável para abrir ModulesDialog."},{name:"config.navigation",type:"SidebarNavigationItem[]",description:"Itens de navegação com label, path, icon e children opcionais"},{name:"config.moduleActions",type:"SidebarActionsConfig",description:"Ações do módulo: triggerLabel, triggerIcon, actions[]"},{name:"customContent",type:"ReactNode",description:"Conteúdo customizado que substitui a navegação padrão"},{name:"resizable",type:"boolean",default:"false",description:"Habilita redimensionamento com drag na borda direita"},{name:"minWidth",type:"number",default:"224",description:"Largura mínima em pixels (resizable=true)"},{name:"maxWidth",type:"number",default:"384",description:"Largura máxima em pixels (resizable=true)"}],accessibility:["Navegação acessível via teclado (Tab, Arrow keys, Enter)","Submenus expansíveis com Enter ou Space (via Collapsible)","Estado ativo comunicado via isActive no SidebarMenuButton","Itens desabilitados com cursor-not-allowed e opacity reduzida","Tooltips em modo colapsado para identificação de todos os itens","Botão pin/unpin oculto em mobile (hidden md:block) para evitar conflito com drawer","Contraste adequado entre estados ativo/inativo usando tokens semânticos"],notes:["✅ Use ícones consistentes do Lucide React para todos os itens","✅ Máximo 2 níveis de aninhamento (item → children)","✅ Labels curtas: 1-3 palavras, máximo 20 caracteres","✅ Agrupe itens relacionados logicamente","✅ Use permissionCheck para controle de acesso assíncrono","✅ Use moduleActions para ações de criação/adição do módulo","✅ Prefira AppLayout ao invés de usar AppSidebar diretamente","❌ Não use mais de 10 itens no nível raiz","❌ Não crie 3+ níveis de submenu (hierarquia profunda)","❌ Não deixe itens sem ícones","❌ Não misture ícones de bibliotecas diferentes","❌ Não use labels com mais de 20 caracteres"],children:[e.jsxs("div",{id:"tipos-typescript",className:"space-y-6 scroll-mt-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Tipos TypeScript"}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:"SidebarConfig"}),e.jsx("pre",{className:"bg-muted p-4 rounded-lg overflow-x-auto text-sm",children:`interface SidebarConfig {
169
- appName?: string;
170
- navigation?: SidebarNavigationItem[];
171
- moduleActions?: SidebarActionsConfig;
172
- }`})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:"SidebarNavigationItem"}),e.jsx("pre",{className:"bg-muted p-4 rounded-lg overflow-x-auto text-sm",children:`interface SidebarNavigationItem {
173
- label: string; // Texto do item
174
- path: string; // Rota de navegação
175
- icon: LucideIcon; // Ícone obrigatório
176
- complementaryText?: string; // Texto complementar
177
- permissionCheck?: () => Promise<boolean>; // Verificação assíncrona
178
- children?: SidebarNavigationItem[]; // Subitens (máx. 2 níveis)
179
- }`})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:"SidebarActionsConfig"}),e.jsx("pre",{className:"bg-muted p-4 rounded-lg overflow-x-auto text-sm",children:`interface SidebarActionsConfig {
180
- triggerLabel?: string; // Rótulo do gatilho (default: 'Criar')
181
- triggerIcon?: LucideIcon; // Ícone do gatilho (default: Plus)
182
- actions: SidebarModuleAction[];
183
- }
184
-
185
- interface SidebarModuleAction {
186
- id: string; // ID único
187
- label: string; // Texto exibido
188
- icon?: LucideIcon; // Ícone opcional
189
- onClick: () => void; // Callback
190
- disabled?: boolean; // Desabilitar ação
191
- permissionCheck?: () => Promise<boolean>; // Verificação de permissão
192
- }`})]})]}),e.jsxs("div",{id:"componente-base",className:"space-y-6 scroll-mt-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Componente Base: Sidebar"}),e.jsxs("p",{className:"text-muted-foreground",children:["O AppSidebar utiliza internamente o componente base ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"Sidebar"})," do Shadcn/Radix. Para sidebars customizadas fora do AppLayout, use o componente base diretamente."]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:"Uso do Base"}),e.jsx("pre",{className:"bg-muted p-4 rounded-lg overflow-x-auto text-sm",children:`import {
193
- Sidebar, SidebarProvider, SidebarHeader, SidebarContent,
194
- SidebarFooter, SidebarGroup, SidebarGroupLabel,
195
- SidebarGroupContent, SidebarMenu, SidebarMenuItem,
196
- SidebarMenuButton, SidebarTrigger,
197
- } from 'forlogic-core';
198
-
199
- <SidebarProvider>
200
- <Sidebar collapsible="icon">
201
- <SidebarHeader>Logo</SidebarHeader>
202
- <SidebarContent>
203
- <SidebarGroup>
204
- <SidebarGroupLabel>Menu</SidebarGroupLabel>
205
- <SidebarGroupContent>
206
- <SidebarMenu>
207
- <SidebarMenuItem>
208
- <SidebarMenuButton isActive>
209
- <Home className="mr-2" /> Home
210
- </SidebarMenuButton>
211
- </SidebarMenuItem>
212
- </SidebarMenu>
213
- </SidebarGroupContent>
214
- </SidebarGroup>
215
- </SidebarContent>
216
- </Sidebar>
217
- <main>
218
- <SidebarTrigger />
219
- {/* Content */}
220
- </main>
221
- </SidebarProvider>`})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:"Props do Sidebar Base"}),e.jsx("div",{className:"rounded-lg border",children:e.jsxs("table",{className:"w-full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b bg-muted/50",children:[e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Prop"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Tipo"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Padrão"}),e.jsx("th",{className:"px-4 py-3 text-left text-sm font-semibold",children:"Descrição"})]})}),e.jsxs("tbody",{children:[e.jsxs("tr",{className:"border-b",children:[e.jsx("td",{className:"px-4 py-3 font-mono text-sm font-medium",children:"side"}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:'"left" | "right"'}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:'"left"'}),e.jsx("td",{className:"px-4 py-3 text-sm",children:"Lado da tela"})]}),e.jsxs("tr",{className:"border-b",children:[e.jsx("td",{className:"px-4 py-3 font-mono text-sm font-medium",children:"variant"}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:'"sidebar" | "floating" | "inset"'}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:'"sidebar"'}),e.jsx("td",{className:"px-4 py-3 text-sm",children:"Estilo visual"})]}),e.jsxs("tr",{className:"border-b last:border-0",children:[e.jsx("td",{className:"px-4 py-3 font-mono text-sm font-medium",children:"collapsible"}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:'"offcanvas" | "icon" | "none"'}),e.jsx("td",{className:"px-4 py-3 font-mono text-sm text-muted-foreground",children:'"offcanvas"'}),e.jsx("td",{className:"px-4 py-3 text-sm",children:"Comportamento de collapse"})]})]})]})})]}),e.jsx("div",{className:"p-4 bg-muted/50 rounded-lg border",children:e.jsxs("p",{className:"text-sm",children:[e.jsx("strong",{children:"💡 Recomendação:"})," Para a maioria dos casos, prefira"," ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"AppSidebar"})," via"," ",e.jsx("code",{className:"bg-muted px-1 rounded",children:"AppLayout"}),", que já inclui permissões, módulos, resize e pin/unpin. Use o Sidebar base apenas para customizações avançadas."]})})]})]})}export{ne as AppSidebarDoc};