@snksergio/design-system 0.56.0 → 0.57.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.
@@ -5276,11 +5276,25 @@ const schedulerRoot = avatar.tv({
5276
5276
  });
5277
5277
  const schedulerToolbar = avatar.tv({
5278
5278
  base: [
5279
- "flex flex-wrap items-center justify-between gap-gp-xl"
5279
+ "flex flex-col gap-gp-xl",
5280
+ "lg:flex-row lg:flex-wrap lg:items-center lg:justify-between"
5280
5281
  ]
5281
5282
  });
5282
5283
  const schedulerToolbarSide = avatar.tv({
5283
- base: "flex min-w-0 flex-wrap items-center gap-gp-md"
5284
+ base: "flex min-w-0 items-center gap-gp-md",
5285
+ variants: {
5286
+ /**
5287
+ * `leading` = título + navegação. Empilhado, ocupa a linha inteira e
5288
+ * separa os dois extremos — é o que joga `‹ Hoje ›` pro fim.
5289
+ * `trailing` = busca + controles. A busca é quem estica (`flex-1` nela),
5290
+ * então aqui basta ocupar a linha.
5291
+ */
5292
+ slot: {
5293
+ leading: "w-full justify-between lg:w-auto lg:flex-wrap lg:justify-start",
5294
+ trailing: "w-full lg:w-auto lg:flex-wrap"
5295
+ }
5296
+ },
5297
+ defaultVariants: { slot: "trailing" }
5284
5298
  });
5285
5299
  const schedulerTitle = avatar.tv({
5286
5300
  base: [
@@ -5320,15 +5334,15 @@ const schedulerSearch = avatar.tv({
5320
5334
  "border border-border-subtle dark:border-border-input",
5321
5335
  "shadow-sh-sm dark:shadow-sh-none",
5322
5336
  "text-fg-default",
5323
- "min-w-0 flex-1 md:flex-initial",
5324
- "md:w-[200px] md:focus-within:w-[300px]",
5337
+ "min-w-0 flex-1 lg:flex-initial",
5338
+ "lg:w-[200px] lg:focus-within:w-[300px]",
5325
5339
  "transition-[width,border-color,background-color,box-shadow] duration-200",
5326
5340
  "focus-within:border-border-brand focus-within:shadow-sh-ring",
5327
5341
  "[&_svg]:size-icon-sm [&_svg]:shrink-0 [&_svg]:text-fg-muted"
5328
5342
  ],
5329
5343
  variants: {
5330
5344
  /** Mantém expandido mesmo sem foco quando já há termo digitado. */
5331
- expanded: { true: "md:w-[300px]", false: "" }
5345
+ expanded: { true: "lg:w-[300px]", false: "" }
5332
5346
  },
5333
5347
  defaultVariants: { expanded: false }
5334
5348
  });
@@ -5391,13 +5405,32 @@ const schedulerMain = avatar.tv({
5391
5405
  });
5392
5406
  const schedulerFilterAside = avatar.tv({
5393
5407
  base: [
5394
- "flex w-[280px] min-h-0 shrink-0 flex-col overflow-y-auto",
5408
+ "flex min-h-0 flex-col overflow-y-auto",
5395
5409
  // `scrollbar-thin` é a barra do DS (26 usos no repo contra 2 do
5396
5410
  // `scrollbar-default`) — trilho transparente + thumb tokenizado.
5397
5411
  // ⚠️ É `@utility` do tema GERADO, não do globals.css: existe nos 4 canais.
5398
- "scrollbar-thin",
5399
- "rounded-radius-xl border border-border-default bg-bg-surface"
5400
- ]
5412
+ "scrollbar-thin"
5413
+ ],
5414
+ variants: {
5415
+ /**
5416
+ * `embedded` = o painel vive DENTRO de outro contêiner que já é a
5417
+ * superfície — hoje o `FloatingPanel` do modo drawer (<1024px).
5418
+ *
5419
+ * Como coluna (`false`, o default) ele É o card: largura própria, borda,
5420
+ * radius e fundo. Embutido, os quatro viram defeito — largura fixa deixa
5421
+ * uma faixa morta à direita do drawer, e borda+radius+fundo repetem a
5422
+ * superfície do painel que já o embrulha (card dentro de card, a mesma
5423
+ * classe de erro da L-050).
5424
+ */
5425
+ embedded: {
5426
+ false: [
5427
+ "w-[280px] shrink-0",
5428
+ "rounded-radius-xl border border-border-default bg-bg-surface"
5429
+ ],
5430
+ true: "w-full"
5431
+ }
5432
+ },
5433
+ defaultVariants: { embedded: false }
5401
5434
  });
5402
5435
  const schedulerAsideSection = avatar.tv({
5403
5436
  base: [
@@ -5867,7 +5900,6 @@ function SchedulerToolbar({
5867
5900
  appliedCount,
5868
5901
  filterPanelOpen,
5869
5902
  onToggleFilterPanel,
5870
- filterPanelAvailable,
5871
5903
  toolbarActions,
5872
5904
  primaryAction
5873
5905
  }) {
@@ -5879,7 +5911,7 @@ function SchedulerToolbar({
5879
5911
  );
5880
5912
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-gp-xl", children: [
5881
5913
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerToolbar(), children: [
5882
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerToolbarSide(), children: [
5914
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerToolbarSide({ slot: "leading" }), children: [
5883
5915
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: schedulerTitle(), children: title2 }),
5884
5916
  /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "group", "aria-label": "Navegação de período", className: schedulerNavGroup(), children: [
5885
5917
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5907,7 +5939,7 @@ function SchedulerToolbar({
5907
5939
  )
5908
5940
  ] })
5909
5941
  ] }),
5910
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerToolbarSide(), children: [
5942
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerToolbarSide({ slot: "trailing" }), children: [
5911
5943
  searchable ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: schedulerSearch({ expanded: search !== "" }), children: [
5912
5944
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { "aria-hidden": "true" }),
5913
5945
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5931,10 +5963,10 @@ function SchedulerToolbar({
5931
5963
  color: "secondary",
5932
5964
  size: "sm",
5933
5965
  iconLeft: activeView.icon,
5934
- iconRight: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}),
5966
+ iconRight: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "hidden lg:block" }),
5935
5967
  "aria-label": `Visualização: ${activeView.label}`,
5936
- className: "shrink-0",
5937
- children: activeView.label
5968
+ className: "shrink-0 max-lg:size-form-xl max-lg:p-0",
5969
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden lg:inline", children: activeView.label })
5938
5970
  }
5939
5971
  ) }),
5940
5972
  /* @__PURE__ */ jsxRuntime.jsx(avatar.DropdownMenuContent, { align: "end", className: "min-w-[168px]", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -5958,13 +5990,13 @@ function SchedulerToolbar({
5958
5990
  size: "sm",
5959
5991
  iconLeft: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListFilter, {}),
5960
5992
  onClick: onToggleFilterPanel,
5961
- disabled: !filterPanelAvailable,
5962
5993
  "aria-expanded": filterPanelOpen,
5963
5994
  className: avatar.cn(
5995
+ "max-lg:size-form-xl max-lg:p-0",
5964
5996
  filterEngaged && "border-border-brand hover:border-border-brand"
5965
5997
  ),
5966
- title: filterPanelAvailable ? void 0 : "O painel de filtros precisa de uma tela mais larga (1024px+)",
5967
- children: "Filtro"
5998
+ "aria-label": "Filtro",
5999
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden lg:inline", children: "Filtro" })
5968
6000
  }
5969
6001
  ),
5970
6002
  appliedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: schedulerFilterDot(), "aria-hidden": "true" }) : null
@@ -6262,6 +6294,7 @@ function SchedulerFilterPanel({
6262
6294
  onClearAll,
6263
6295
  appliedCount,
6264
6296
  onClose,
6297
+ embedded = false,
6265
6298
  counts,
6266
6299
  date,
6267
6300
  now,
@@ -6277,8 +6310,8 @@ function SchedulerFilterPanel({
6277
6310
  else next.add(id);
6278
6311
  return next;
6279
6312
  });
6280
- return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: schedulerFilterAside(), "aria-label": "Filtros do calendário", children: [
6281
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: schedulerAsideSection({ compact: true, sticky: true }), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerAsideHead(), children: [
6313
+ return /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: schedulerFilterAside({ embedded }), "aria-label": "Filtros do calendário", children: [
6314
+ embedded ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: schedulerAsideSection({ compact: true, sticky: true }), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: schedulerAsideHead(), children: [
6282
6315
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: schedulerAsideTitle(), children: "Filtros" }),
6283
6316
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-gp-sm", children: [
6284
6317
  appliedCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onClearAll, className: schedulerClearLink(), children: "Limpar" }) : null,
@@ -7608,9 +7641,11 @@ const Scheduler = React.forwardRef(
7608
7641
  return;
7609
7642
  }, [draggable, resizable, onEventMove, onEventResize]);
7610
7643
  const eventoArrastado = dnd.dragAtivo?.kind === "move" ? filter.filteredEvents.find((e) => e.id === dnd.dragAtivo?.eventId) ?? null : null;
7611
- const filterPanelAvailable = useMediaQuery("(min-width: 1024px)");
7644
+ const wideLayout = useMediaQuery("(min-width: 1024px)");
7612
7645
  const [filterPanelOpen, setFilterPanelOpen] = React.useState(defaultFilterPanelOpen);
7613
- const showFilterPanel = filterPanelOpen && filterPanelAvailable && (filterFields?.length ?? 0) > 0;
7646
+ const hasFilterFields = (filterFields?.length ?? 0) > 0;
7647
+ const showFilterPanel = filterPanelOpen && wideLayout && hasFilterFields;
7648
+ const showFilterDrawer = filterPanelOpen && !wideLayout && hasFilterFields;
7614
7649
  React.useImperativeHandle(
7615
7650
  ref,
7616
7651
  () => ({
@@ -7677,9 +7712,8 @@ const Scheduler = React.forwardRef(
7677
7712
  onClearField: filter.clearField,
7678
7713
  onClearAll: filter.clearAll,
7679
7714
  appliedCount: filter.appliedCount,
7680
- filterPanelOpen: showFilterPanel,
7715
+ filterPanelOpen: showFilterPanel || showFilterDrawer,
7681
7716
  onToggleFilterPanel: () => setFilterPanelOpen((o) => !o),
7682
- filterPanelAvailable,
7683
7717
  toolbarActions,
7684
7718
  primaryAction
7685
7719
  }
@@ -7756,6 +7790,52 @@ const Scheduler = React.forwardRef(
7756
7790
  }
7757
7791
  ) : null
7758
7792
  ] }),
7793
+ showFilterDrawer && filterFields ? /* @__PURE__ */ jsxRuntime.jsx(
7794
+ panel.FloatingPanel,
7795
+ {
7796
+ open: true,
7797
+ onOpenChange: (aberto) => setFilterPanelOpen(aberto),
7798
+ side: "right",
7799
+ size: "sm",
7800
+ bodyPadded: false,
7801
+ title: "Filtros",
7802
+ titleIcon: lucideReact.ListFilter,
7803
+ description: filter.appliedCount === 1 ? "1 filtro ativo" : `${filter.appliedCount} filtros ativos`,
7804
+ footer: /* @__PURE__ */ jsxRuntime.jsx(
7805
+ avatar.Button,
7806
+ {
7807
+ variant: "ghost",
7808
+ color: "secondary",
7809
+ size: "sm",
7810
+ onClick: filter.clearAll,
7811
+ disabled: filter.appliedCount === 0,
7812
+ children: "Limpar tudo"
7813
+ }
7814
+ ),
7815
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7816
+ SchedulerFilterPanel,
7817
+ {
7818
+ embedded: true,
7819
+ filterFields,
7820
+ filterModel: filter.filterModel,
7821
+ onToggleValue: filter.toggleValue,
7822
+ onClearAll: filter.clearAll,
7823
+ appliedCount: filter.appliedCount,
7824
+ onClose: () => setFilterPanelOpen(false),
7825
+ counts: filter.optionCounts,
7826
+ date: state.date,
7827
+ now,
7828
+ locale,
7829
+ weekStartsOn,
7830
+ events: filter.filteredEvents,
7831
+ onDateSelect: (d) => {
7832
+ state.goToDate(d);
7833
+ setFilterPanelOpen(false);
7834
+ }
7835
+ }
7836
+ )
7837
+ }
7838
+ ) : null,
7759
7839
  /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { dropAnimation: null, children: eventoArrastado ? /* @__PURE__ */ jsxRuntime.jsx(
7760
7840
  SchedulerEventItem,
7761
7841
  {