@snksergio/design-system 0.65.0 → 0.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist-lib/ai/componentes/AppShell.md +13 -8
  2. package/dist-lib/ai/componentes/SingleMenuSidebar.md +27 -0
  3. package/dist-lib/ai/manifest.json +2 -2
  4. package/dist-lib/ai/regras-por-componente.json +3 -2
  5. package/dist-lib/ai/roteiros/app-builder/roteiro.md +7 -0
  6. package/dist-lib/chunks/{avatar-CMWPg3A3.cjs → avatar-B7h09dye.cjs} +3 -3
  7. package/dist-lib/chunks/{avatar-CMWPg3A3.cjs.map → avatar-B7h09dye.cjs.map} +1 -1
  8. package/dist-lib/chunks/{avatar-CZRLkTxt.mjs → avatar-hOzvQo9K.mjs} +3 -3
  9. package/dist-lib/chunks/{avatar-CZRLkTxt.mjs.map → avatar-hOzvQo9K.mjs.map} +1 -1
  10. package/dist-lib/chunks/{input-BQABJR2N.mjs → input-BPsqrMAw.mjs} +2 -2
  11. package/dist-lib/chunks/{input-BQABJR2N.mjs.map → input-BPsqrMAw.mjs.map} +1 -1
  12. package/dist-lib/chunks/{input-DqaLFxER.cjs → input-DwQ6HFRu.cjs} +2 -2
  13. package/dist-lib/chunks/{input-DqaLFxER.cjs.map → input-DwQ6HFRu.cjs.map} +1 -1
  14. package/dist-lib/chunks/{kpi-delta-iKhYhdD1.mjs → kpi-delta-CU6JxXSb.mjs} +3 -3
  15. package/dist-lib/chunks/{kpi-delta-iKhYhdD1.mjs.map → kpi-delta-CU6JxXSb.mjs.map} +1 -1
  16. package/dist-lib/chunks/{kpi-delta-BDrsKM-f.cjs → kpi-delta-ous1beKW.cjs} +3 -3
  17. package/dist-lib/chunks/{kpi-delta-BDrsKM-f.cjs.map → kpi-delta-ous1beKW.cjs.map} +1 -1
  18. package/dist-lib/chunks/{page-header-t5hFIp7o.mjs → page-header-CiElo3dw.mjs} +2 -2
  19. package/dist-lib/chunks/{page-header-t5hFIp7o.mjs.map → page-header-CiElo3dw.mjs.map} +1 -1
  20. package/dist-lib/chunks/{page-header-sValhWca.cjs → page-header-DEBrPvwk.cjs} +2 -2
  21. package/dist-lib/chunks/{page-header-sValhWca.cjs.map → page-header-DEBrPvwk.cjs.map} +1 -1
  22. package/dist-lib/chunks/{panel-BihHQ-sP.cjs → panel-BA-COEiW.cjs} +5 -5
  23. package/dist-lib/chunks/{panel-BihHQ-sP.cjs.map → panel-BA-COEiW.cjs.map} +1 -1
  24. package/dist-lib/chunks/{panel-B7uZTYVh.mjs → panel-Ccy88Gnd.mjs} +5 -5
  25. package/dist-lib/chunks/{panel-B7uZTYVh.mjs.map → panel-Ccy88Gnd.mjs.map} +1 -1
  26. package/dist-lib/chunks/{sheet-Bjjo4ZaT.mjs → sheet-BBrZkT_x.mjs} +4 -4
  27. package/dist-lib/chunks/sheet-BBrZkT_x.mjs.map +1 -0
  28. package/dist-lib/chunks/{sheet-BrYriaDN.cjs → sheet-n_XtAcqI.cjs} +4 -4
  29. package/dist-lib/chunks/sheet-n_XtAcqI.cjs.map +1 -0
  30. package/dist-lib/chunks/{toggle-group-DeoBmogo.cjs → toggle-group-CgDOdmWM.cjs} +7 -7
  31. package/dist-lib/chunks/toggle-group-CgDOdmWM.cjs.map +1 -0
  32. package/dist-lib/chunks/{toggle-group-XMgZgL-H.mjs → toggle-group-WBUjC4-0.mjs} +7 -7
  33. package/dist-lib/chunks/toggle-group-WBUjC4-0.mjs.map +1 -0
  34. package/dist-lib/chunks/{useTheme-N5Nc0jdR.cjs → useTheme-CM-9qLsP.cjs} +7 -3
  35. package/dist-lib/chunks/{useTheme-N5Nc0jdR.cjs.map → useTheme-CM-9qLsP.cjs.map} +1 -1
  36. package/dist-lib/chunks/{useTheme-DwhMIlTr.mjs → useTheme-DSHndxZC.mjs} +7 -3
  37. package/dist-lib/chunks/{useTheme-DwhMIlTr.mjs.map → useTheme-DSHndxZC.mjs.map} +1 -1
  38. package/dist-lib/index.cjs +8 -8
  39. package/dist-lib/index.mjs +14 -14
  40. package/dist-lib/preview/chat.cjs +3 -3
  41. package/dist-lib/preview/chat.mjs +3 -3
  42. package/dist-lib/preview/clientes.cjs +6 -6
  43. package/dist-lib/preview/clientes.mjs +6 -6
  44. package/dist-lib/preview/dashboard.cjs +4 -4
  45. package/dist-lib/preview/dashboard.mjs +4 -4
  46. package/dist-lib/shadcn.cjs +4 -4
  47. package/dist-lib/shadcn.mjs +4 -4
  48. package/dist-lib/src/components/ui/AppShell/app-shell.d.ts.map +1 -1
  49. package/dist-lib/src/components/ui/AppShell/app-shell.types.d.ts +13 -0
  50. package/dist-lib/src/components/ui/AppShell/app-shell.types.d.ts.map +1 -1
  51. package/dist-lib/src/components/ui/SingleMenuSidebar/single-menu-sidebar.d.ts +1 -1
  52. package/dist-lib/src/components/ui/SingleMenuSidebar/single-menu-sidebar.d.ts.map +1 -1
  53. package/dist-lib/src/components/ui/SingleMenuSidebar/single-menu-sidebar.types.d.ts +12 -0
  54. package/dist-lib/src/components/ui/SingleMenuSidebar/single-menu-sidebar.types.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/dist-lib/chunks/sheet-Bjjo4ZaT.mjs.map +0 -1
  57. package/dist-lib/chunks/sheet-BrYriaDN.cjs.map +0 -1
  58. package/dist-lib/chunks/toggle-group-DeoBmogo.cjs.map +0 -1
  59. package/dist-lib/chunks/toggle-group-XMgZgL-H.mjs.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- ds:regras
4
4
  - tem áreas separadas (Comercial, Financeiro…)? → `sidebar="menu"` + `contexts`. Não tem? → `"single"` + `categories`, sem `sidebarModules` nem `sidebarShowSearch`
5
- - **exceção: o app tem ESCOPO global** (empresa/unidade que recorta TODAS as páginas)? → `sidebarModule` (seletor, não troca menu) + `sidebarShowSearch` + `sidebarSearchCommand` (a paleta vira a seleção das unidades). NÃO é `sidebarModules`: aquele troca as `categories`
5
+ - **exceção: o app tem ESCOPO global** (empresa/unidade que recorta TODAS as páginas)? → `sidebarModule` (seletor, não troca menu) + `sidebarTopSlot` (o multi-select das unidades, montado por você). NÃO é `sidebarModules` (troca as `categories`) nem `sidebarSearchCommand` (aquele é a paleta da BUSCA)
6
6
  - NÃO passe `sidebarLogo`: o default é a marca iGreen. Só com marca própria pedida explicitamente
7
7
  - `sidebarTitle` = nome do projeto (vai à direita da logo) — pergunte, não invente
8
8
  -->
@@ -69,14 +69,19 @@ sem erro nenhum.
69
69
  | `sidebarModule` | SingleMenuModule | — | **Seletor de ESCOPO** (empresa, workspace, unidade): ícone + título + subtítulo e, com `options`, dropdown. **Não troca o menu** — é a diferença com o plural acima. Use quando o menu é o mesmo em todas as opções; o plural, quando cada uma tem o seu. Passar os dois é erro: o seletor é um só |
70
70
  | `sidebarShowSearch` | boolean | — | Busca no topo da sidebar (é um botão que abre command palette, não um input) |
71
71
  | `sidebarSearchPlaceholder` | string | — | Placeholder da busca **da sidebar** — distinto do `searchPlaceholder`, que é do Header |
72
- | `sidebarSearchCommand` | ReactNode | itens do menu | Conteúdo do `CommandList` da paleta da busca. Com ele o campo deixa de ser busca de menu e vira **seleção de escopo** (locais, filiais, safras). Exige `sidebarShowSearch`; pareie com `sidebarSearchPlaceholder` pra renomear o gatilho |
72
+ | `sidebarSearchCommand` | ReactNode | itens do menu | Conteúdo do `CommandList` da paleta da busca **da sidebar**. Troca a lista de itens do menu por outra lista **de busca**. Exige `sidebarShowSearch`. ⛔ **Não é o lugar de um controle de escopo** — pra isso é `sidebarTopSlot` |
73
+ | `sidebarTopSlot` | ReactNode | — | **Slot livre no topo da sidebar**, entre o seletor de módulo e a busca. É aqui que vai controle de **escopo** que não é seletor único nem busca: multi-select de unidades, filtro de safra, período global. Você monta o controle; o shell reserva o lugar |
73
74
 
74
- > **`sidebarModule` + `sidebarSearchCommand` = escopo global sem componente novo.** É o
75
- > padrão "empresa no seletor, unidades na paleta" de CMS multi-tenant: o topo da sidebar
76
- > vira o recorte que todas as páginas obedecem. As duas props existiam no
77
- > `SingleMenuSidebar` desde sempre e **não eram repassadas** pelo shell até 2026-09-16 —
78
- > quem precisava era empurrado pro `sidebarModules` com N entradas de categorias
79
- > idênticas, que funciona por acidente. Gate: `sidebar-single-escopo.test.tsx`.
75
+ > **`sidebarModule` + `sidebarTopSlot` = escopo global sem componente novo.** É o padrão
76
+ > "empresa no seletor, unidades logo abaixo" de CMS multi-tenant: o topo da sidebar vira o
77
+ > recorte que todas as páginas obedecem, encostado na navegação que ele recorta.
78
+ >
79
+ > ⚠️ **A primeira versão disto usou `sidebarSearchCommand` e ficou ruim.** O gatilho da
80
+ > busca é um botão com lupa e badge `⌘K`, sem prop pra esconder nenhum dos dois: o controle
81
+ > de escopo se apresentava como busca, e o rodapé "Selecionar todas / Limpar" rolava junto
82
+ > com a lista (ele vive dentro do `CommandList`, que É a área de scroll). **Busca é busca.**
83
+ > Conteúdo arbitrário pede slot arbitrário — daí o `sidebarTopSlot` (2026-09-16).
84
+ > Gate: `sidebar-single-escopo.test.tsx`.
80
85
  | `defaultActiveContextId` | string | primeiro do array | Workspace inicial (uncontrolled) |
81
86
  | `activeContextId` | string | — | Workspace ativo (controlled) |
82
87
  | `onContextChange` | (id: string) => void | — | Callback de troca de workspace |
@@ -4,6 +4,7 @@
4
4
  - NÃO passe `logo`: o default é a marca iGreen. Só com marca própria pedida explicitamente
5
5
  - `title` = nome do projeto (vai à direita da logo) — pergunte, não invente
6
6
  - é a escolha quando NÃO há divisão em áreas: `showSearch={false}`, sem `module`/`modules`
7
+ - controle de ESCOPO no topo (multi-select de unidades, filtro de safra, período global)? → `topSlot`. NUNCA `searchCommand`: busca é busca
7
8
  -->
8
9
 
9
10
  **O que é** — Sidebar de navegação de **nível único**: categoria → sub-itens em
@@ -43,6 +44,7 @@ exibido à direita dela.
43
44
  | `showSearch` | `boolean` | `true` | |
44
45
  | `searchCommand` | `ReactNode` | — | |
45
46
  | `searchPlaceholder` | `string` | — | |
47
+ | `topSlot` | `ReactNode` | — | slot livre entre o módulo e a busca |
46
48
  | `activeItemId` | `string` | — | |
47
49
  | `onItemClick` | `(id: string) => void` | — | |
48
50
  | `defaultExpanded` | `boolean` | `true` | |
@@ -55,6 +57,31 @@ abre um `CommandDialog`: você passa o **conteúdo** dele em `searchCommand` e,
55
57
  texto do placeholder em `searchPlaceholder`. As props `value`/`onChange`/`inputRef` existem
56
58
  em `SingleMenuSearchProps`, que é subcomponente interno.
57
59
 
60
+ ### `topSlot` — escopo no topo, e por que não é a busca
61
+
62
+ O bloco do topo tem três lugares, nesta ordem: **seletor de módulo → `topSlot` → busca**.
63
+
64
+ `topSlot` é um slot livre. Ponha ali o controle que responde *"sobre o que estou olhando"*
65
+ e não é um seletor único: multi-select de unidades/filiais, filtro de safra, período global.
66
+ Você monta o controle com os componentes que quiser — o componente só reserva o lugar.
67
+
68
+ ```tsx
69
+ <SingleMenuSidebar
70
+ title="iGreen MOB"
71
+ module={{ icon: <Building2 />, title: empresa, subtitle: "Empresa selecionada" }}
72
+ topSlot={<SeletorDeLocais valor={locais} onChange={setLocais} />}
73
+ showSearch={false}
74
+ categories={CATEGORIAS}
75
+ />
76
+ ```
77
+
78
+ ⛔ **Não use `searchCommand` pra isso.** Aquele troca o conteúdo da paleta da **busca**, e o
79
+ gatilho dela é um `<button>` fixo com lupa e badge `⌘K` — sem prop pra esconder nenhum dos
80
+ dois. Um controle de escopo ali **se apresenta como busca**, e um rodapé de ações ("Selecionar
81
+ todas" / "Limpar") rola junto com a lista, porque ele vive dentro do `CommandList`, que É a
82
+ área de scroll. Medido num consumidor real em 2026-09-16: foi esse desvio que originou o
83
+ `topSlot`. Gate: `AppShell/sidebar-single-escopo.test.tsx`.
84
+
58
85
  ### Multi-módulo
59
86
 
60
87
  `modules` é a API pra sidebar que troca de contexto: cada `SingleMenuModuleConfig` traz suas
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "pacote": "@snksergio/design-system",
3
- "versao": "0.65.0",
4
- "commit": "956f38c",
3
+ "versao": "0.66.0",
4
+ "commit": "e85efd7",
5
5
  "gerado": "2026-09-16",
6
6
  "conteudo": {
7
7
  "roteiros": [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "AppShell": [
3
3
  "tem áreas separadas (Comercial, Financeiro…)? → `sidebar=\"menu\"` + `contexts`. Não tem? → `\"single\"` + `categories`, sem `sidebarModules` nem `sidebarShowSearch`",
4
- "**exceção: o app tem ESCOPO global** (empresa/unidade que recorta TODAS as páginas)? → `sidebarModule` (seletor, não troca menu) + `sidebarShowSearch` + `sidebarSearchCommand` (a paleta vira a seleção das unidades). NÃO é `sidebarModules`: aquele troca as `categories`",
4
+ "**exceção: o app tem ESCOPO global** (empresa/unidade que recorta TODAS as páginas)? → `sidebarModule` (seletor, não troca menu) + `sidebarTopSlot` (o multi-select das unidades, montado por você). NÃO é `sidebarModules` (troca as `categories`) nem `sidebarSearchCommand` (aquele é a paleta da BUSCA)",
5
5
  "NÃO passe `sidebarLogo`: o default é a marca iGreen. Só com marca própria pedida explicitamente",
6
6
  "`sidebarTitle` = nome do projeto (vai à direita da logo) — pergunte, não invente"
7
7
  ],
@@ -69,7 +69,8 @@
69
69
  "SingleMenuSidebar": [
70
70
  "NÃO passe `logo`: o default é a marca iGreen. Só com marca própria pedida explicitamente",
71
71
  "`title` = nome do projeto (vai à direita da logo) — pergunte, não invente",
72
- "é a escolha quando NÃO há divisão em áreas: `showSearch={false}`, sem `module`/`modules`"
72
+ "é a escolha quando NÃO há divisão em áreas: `showSearch={false}`, sem `module`/`modules`",
73
+ "controle de ESCOPO no topo (multi-select de unidades, filtro de safra, período global)? → `topSlot`. NUNCA `searchCommand`: busca é busca"
73
74
  ],
74
75
  "TabsNavigation": [
75
76
  "aba de NAVEGADOR (sessão que abre/fecha: conversa, chamado, registro) → `<TabsNavigation>`; filtro de conteúdo dentro da tela → `tabs` do shadcn",
@@ -70,6 +70,13 @@ existe divisão, o rail da `"menu"` mostra as áreas todas de uma vez, enquanto
70
70
  ficam atrás de um botão acima da busca. Quer conhecer as outras variações? Mande a página do
71
71
  componente — ampliar o leque na entrevista é o que produz escolha errada.
72
72
 
73
+ **Terceira resposta possível: o app tem ESCOPO global** — uma empresa/unidade que recorta
74
+ **todas** as páginas ("os dados são sempre dos locais selecionados no topo"). Aí é `"single"`
75
+ + `sidebarModule` (o seletor de escopo — singular, **não** troca o menu) + `sidebarTopSlot`
76
+ (o multi-select das unidades, que você monta). ⛔ **Não** use `sidebarSearchCommand` pra isso:
77
+ aquele é o conteúdo da paleta da **busca**, cujo gatilho tem lupa e `⌘K` fixos — o controle se
78
+ apresenta como busca e o rodapé de ações rola com a lista. Busca é busca.
79
+
73
80
  ```tsx
74
81
  <AppShell
75
82
  sidebar="single"
@@ -1027,7 +1027,7 @@ const CONTAINER_CLASSES = [
1027
1027
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
1028
1028
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
1029
1029
  "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1030
- "origin-[--radix-dropdown-menu-content-transform-origin]"
1030
+ "origin-[var(--radix-dropdown-menu-content-transform-origin)]"
1031
1031
  ].join(" ");
1032
1032
  const MOBILE_SHEET_CLASSES = [
1033
1033
  "max-md:w-full max-md:min-w-0 max-md:max-w-none",
@@ -1212,7 +1212,7 @@ const TooltipContent = React__namespace.forwardRef(({ className, sideOffset = 6,
1212
1212
  "rounded-radius-md px-pad-lg py-pad-xs",
1213
1213
  "text-caption-sm",
1214
1214
  "shadow-sh-md",
1215
- "origin-[--radix-tooltip-content-transform-origin]",
1215
+ "origin-[var(--radix-tooltip-content-transform-origin)]",
1216
1216
  "data-[state=delayed-open]:animate-in data-[state=instant-open]:animate-in data-[state=closed]:animate-out",
1217
1217
  "data-[state=closed]:fade-out-0 data-[state=delayed-open]:fade-in-0 data-[state=instant-open]:fade-in-0",
1218
1218
  "data-[state=closed]:zoom-out-95 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:zoom-in-95",
@@ -1342,4 +1342,4 @@ exports.inputGroupInputVariants = inputGroupInputVariants;
1342
1342
  exports.inputGroupTextareaVariants = inputGroupTextareaVariants;
1343
1343
  exports.inputGroupVariants = inputGroupVariants;
1344
1344
  exports.tv = tv;
1345
- //# sourceMappingURL=avatar-CMWPg3A3.cjs.map
1345
+ //# sourceMappingURL=avatar-B7h09dye.cjs.map