@devfellowship/components 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4751,10 +4751,389 @@ function AppNavbar({
4751
4751
  );
4752
4752
  }
4753
4753
 
4754
- // src/components/organisms/PublishDrawer.tsx
4754
+ // src/components/organisms/Gantt.tsx
4755
4755
  import * as React44 from "react";
4756
- import { Loader2, Youtube, Image as ImageIcon, CheckCircle2, AlertCircle } from "lucide-react";
4757
4756
  import { jsx as jsx63, jsxs as jsxs31 } from "react/jsx-runtime";
4757
+ function clampPct(value) {
4758
+ if (value == null || Number.isNaN(value)) return 0;
4759
+ return Math.max(0, Math.min(100, Math.round(value)));
4760
+ }
4761
+ function stageProgress(stage) {
4762
+ if (stage.progress != null) return clampPct(stage.progress);
4763
+ const ms = stage.milestones ?? [];
4764
+ if (ms.length === 0) return 0;
4765
+ const done = ms.filter((m) => m.done).length;
4766
+ return clampPct(done / ms.length * 100);
4767
+ }
4768
+ function resolveWeekCount(stages, weeks) {
4769
+ if (Array.isArray(weeks)) return Math.max(1, weeks.length);
4770
+ if (typeof weeks === "number" && weeks > 0) return Math.round(weeks);
4771
+ let max = 1;
4772
+ for (const s of stages) {
4773
+ max = Math.max(max, s.weekStart + Math.max(1, s.weekSpan) - 1);
4774
+ for (const m of s.milestones ?? []) {
4775
+ const ws = m.weekStart ?? s.weekStart;
4776
+ max = Math.max(max, ws + Math.max(1, m.weekSpan ?? 1) - 1);
4777
+ }
4778
+ }
4779
+ return Math.max(1, max);
4780
+ }
4781
+ function resolveWeekLabels(count2, weeks) {
4782
+ if (Array.isArray(weeks)) return weeks;
4783
+ return Array.from({ length: count2 }, (_, i) => `W${i + 1}`);
4784
+ }
4785
+ function barGridColumn(weekStart, weekSpan, weekCount) {
4786
+ const start = Math.max(1, Math.min(weekStart, weekCount));
4787
+ const rawEnd = start + Math.max(1, weekSpan) - 1;
4788
+ const end = Math.max(start, Math.min(rawEnd, weekCount));
4789
+ return { start, span: end - start + 1 };
4790
+ }
4791
+ var DEFAULT_DOT = "var(--s-brand-solid, #E07A4A)";
4792
+ function Gantt({
4793
+ stages,
4794
+ weeks,
4795
+ dependencies = [],
4796
+ rowsHeader = "Stage / Task",
4797
+ stagesOnly = false,
4798
+ header,
4799
+ labelWidth = 240,
4800
+ weekMinWidth = 64,
4801
+ className,
4802
+ style,
4803
+ ...rest
4804
+ }) {
4805
+ const weekCount = resolveWeekCount(stages, weeks);
4806
+ const weekLabels = resolveWeekLabels(weekCount, weeks);
4807
+ const [collapsed, setCollapsed] = React44.useState(
4808
+ () => Object.fromEntries(stages.filter((s) => s.collapsed).map((s) => [s.id, true]))
4809
+ );
4810
+ const toggle = (id) => setCollapsed((c) => ({ ...c, [id]: !c[id] }));
4811
+ const gridRef = React44.useRef(null);
4812
+ const barRefs = React44.useRef({});
4813
+ const [edges, setEdges] = React44.useState([]);
4814
+ const recomputeEdges = React44.useCallback(() => {
4815
+ const root = gridRef.current;
4816
+ if (!root || dependencies.length === 0) {
4817
+ setEdges([]);
4818
+ return;
4819
+ }
4820
+ const rootBox = root.getBoundingClientRect();
4821
+ const next = [];
4822
+ for (const dep of dependencies) {
4823
+ const a = barRefs.current[dep.from];
4824
+ const b = barRefs.current[dep.to];
4825
+ if (!a || !b) continue;
4826
+ const ab = a.getBoundingClientRect();
4827
+ const bb = b.getBoundingClientRect();
4828
+ next.push({
4829
+ id: `${dep.from}->${dep.to}`,
4830
+ x1: ab.right - rootBox.left,
4831
+ y1: ab.top - rootBox.top + ab.height / 2,
4832
+ x2: bb.left - rootBox.left,
4833
+ y2: bb.top - rootBox.top + bb.height / 2
4834
+ });
4835
+ }
4836
+ setEdges(next);
4837
+ }, [dependencies]);
4838
+ React44.useLayoutEffect(() => {
4839
+ recomputeEdges();
4840
+ }, [recomputeEdges, collapsed, weekCount, stages]);
4841
+ React44.useEffect(() => {
4842
+ if (dependencies.length === 0) return;
4843
+ const handler = () => recomputeEdges();
4844
+ window.addEventListener("resize", handler);
4845
+ return () => window.removeEventListener("resize", handler);
4846
+ }, [dependencies.length, recomputeEdges]);
4847
+ const trackTemplate = `${labelWidth}px repeat(${weekCount}, minmax(${weekMinWidth}px, 1fr))`;
4848
+ return /* @__PURE__ */ jsxs31(
4849
+ "div",
4850
+ {
4851
+ className: cn(
4852
+ "dfl-gantt rounded-[var(--c-card-radius,10px)] border border-[var(--s-border-subtle,#2A2622)] bg-[var(--s-surface-panel,#141210)] text-[var(--s-ink-primary,#F6F1E7)] overflow-hidden",
4853
+ className
4854
+ ),
4855
+ style,
4856
+ ...rest,
4857
+ children: [
4858
+ header && /* @__PURE__ */ jsx63("div", { className: "border-b border-[var(--s-border-subtle,#2A2622)] px-5 py-4", children: header }),
4859
+ /* @__PURE__ */ jsx63("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs31("div", { ref: gridRef, className: "relative min-w-max", children: [
4860
+ edges.length > 0 && /* @__PURE__ */ jsxs31(
4861
+ "svg",
4862
+ {
4863
+ className: "pointer-events-none absolute inset-0 h-full w-full",
4864
+ "aria-hidden": "true",
4865
+ children: [
4866
+ /* @__PURE__ */ jsx63("defs", { children: /* @__PURE__ */ jsx63(
4867
+ "marker",
4868
+ {
4869
+ id: "dfl-gantt-arrow",
4870
+ markerWidth: "7",
4871
+ markerHeight: "7",
4872
+ refX: "5",
4873
+ refY: "3",
4874
+ orient: "auto",
4875
+ children: /* @__PURE__ */ jsx63(
4876
+ "path",
4877
+ {
4878
+ d: "M0,0 L6,3 L0,6 Z",
4879
+ fill: "var(--s-brand-solid, #E07A4A)"
4880
+ }
4881
+ )
4882
+ }
4883
+ ) }),
4884
+ edges.map((e) => {
4885
+ const stub = 14;
4886
+ const c1x = e.x1 + stub;
4887
+ const c2x = e.x2 - stub;
4888
+ return /* @__PURE__ */ jsx63(
4889
+ "path",
4890
+ {
4891
+ d: `M ${e.x1} ${e.y1} C ${c1x} ${e.y1}, ${c2x} ${e.y2}, ${e.x2} ${e.y2}`,
4892
+ fill: "none",
4893
+ stroke: "var(--s-brand-solid, #E07A4A)",
4894
+ strokeWidth: 1.5,
4895
+ strokeOpacity: 0.65,
4896
+ markerEnd: "url(#dfl-gantt-arrow)"
4897
+ },
4898
+ e.id
4899
+ );
4900
+ })
4901
+ ]
4902
+ }
4903
+ ),
4904
+ /* @__PURE__ */ jsxs31(
4905
+ "div",
4906
+ {
4907
+ className: "grid items-center border-b border-[var(--s-border-subtle,#2A2622)] bg-[var(--s-surface-raised,#1A1714)]",
4908
+ style: { gridTemplateColumns: trackTemplate },
4909
+ children: [
4910
+ /* @__PURE__ */ jsx63("div", { className: "px-4 py-2.5 font-[var(--s-font-mono,monospace)] text-[10.5px] font-medium uppercase tracking-[0.6px] text-[var(--s-ink-muted,#7D7568)]", children: rowsHeader }),
4911
+ weekLabels.map((label, i) => /* @__PURE__ */ jsx63(
4912
+ "div",
4913
+ {
4914
+ className: "border-l border-[var(--s-border-subtle,#2A2622)] py-2.5 text-center font-[var(--s-font-mono,monospace)] text-[11px] tabular-nums text-[var(--s-ink-muted,#7D7568)]",
4915
+ children: label
4916
+ },
4917
+ i
4918
+ ))
4919
+ ]
4920
+ }
4921
+ ),
4922
+ stages.map((stage) => {
4923
+ const pct = stageProgress(stage);
4924
+ const dot = stage.color || DEFAULT_DOT;
4925
+ const isCollapsed = !!collapsed[stage.id];
4926
+ const ms = stage.milestones ?? [];
4927
+ const done = ms.filter((m) => m.done).length;
4928
+ const sCol = barGridColumn(stage.weekStart, stage.weekSpan, weekCount);
4929
+ return /* @__PURE__ */ jsxs31(React44.Fragment, { children: [
4930
+ /* @__PURE__ */ jsxs31(
4931
+ "div",
4932
+ {
4933
+ className: "grid items-center border-b border-[var(--s-border-subtle,#2A2622)]",
4934
+ style: { gridTemplateColumns: trackTemplate },
4935
+ children: [
4936
+ /* @__PURE__ */ jsxs31(
4937
+ "button",
4938
+ {
4939
+ type: "button",
4940
+ onClick: () => toggle(stage.id),
4941
+ className: "flex items-center gap-2 px-4 py-3 text-left hover:bg-[var(--s-surface-raised,#1A1714)] transition-colors",
4942
+ "aria-expanded": !isCollapsed,
4943
+ children: [
4944
+ /* @__PURE__ */ jsx63(Chevron, { open: !isCollapsed }),
4945
+ /* @__PURE__ */ jsx63(
4946
+ "span",
4947
+ {
4948
+ className: "h-2.5 w-2.5 shrink-0 rounded-full",
4949
+ style: { background: dot }
4950
+ }
4951
+ ),
4952
+ /* @__PURE__ */ jsxs31("span", { className: "min-w-0", children: [
4953
+ /* @__PURE__ */ jsx63("span", { className: "block truncate text-[13px] font-semibold text-[var(--s-ink-primary,#F6F1E7)]", children: stage.title }),
4954
+ stage.subtitle && /* @__PURE__ */ jsx63("span", { className: "block truncate text-[11px] text-[var(--s-ink-muted,#7D7568)]", children: stage.subtitle })
4955
+ ] }),
4956
+ ms.length > 0 && /* @__PURE__ */ jsxs31("span", { className: "ml-auto shrink-0 rounded-[var(--c-badge-radius,4px)] bg-[var(--s-surface-elevated,#1F1C18)] px-1.5 py-0.5 font-[var(--s-font-mono,monospace)] text-[10px] tabular-nums text-[var(--s-ink-secondary,#C9C0B4)]", children: [
4957
+ done,
4958
+ "/",
4959
+ ms.length
4960
+ ] })
4961
+ ]
4962
+ }
4963
+ ),
4964
+ /* @__PURE__ */ jsx63(
4965
+ "div",
4966
+ {
4967
+ className: "relative h-9",
4968
+ style: {
4969
+ gridColumn: `${1 + sCol.start} / span ${sCol.span}`
4970
+ },
4971
+ children: /* @__PURE__ */ jsxs31(
4972
+ "div",
4973
+ {
4974
+ ref: (el) => {
4975
+ barRefs.current[stage.id] = el;
4976
+ },
4977
+ className: "absolute inset-y-2 inset-x-1 overflow-hidden rounded-[var(--p-radius-sm,4px)]",
4978
+ style: { background: tint(dot, 0.16) },
4979
+ title: `${stage.title} \xB7 ${pct}%`,
4980
+ children: [
4981
+ /* @__PURE__ */ jsx63(
4982
+ "div",
4983
+ {
4984
+ className: "h-full rounded-[var(--p-radius-sm,4px)]",
4985
+ style: { width: `${pct}%`, background: dot }
4986
+ }
4987
+ ),
4988
+ /* @__PURE__ */ jsxs31("span", { className: "absolute inset-0 flex items-center px-2 font-[var(--s-font-mono,monospace)] text-[10.5px] font-medium tabular-nums text-[var(--s-ink-primary,#F6F1E7)]", children: [
4989
+ pct,
4990
+ "%"
4991
+ ] })
4992
+ ]
4993
+ }
4994
+ )
4995
+ }
4996
+ )
4997
+ ]
4998
+ }
4999
+ ),
5000
+ !stagesOnly && !isCollapsed && ms.map((m) => {
5001
+ const mStart = m.weekStart ?? stage.weekStart;
5002
+ const mCol = barGridColumn(
5003
+ mStart,
5004
+ m.weekSpan ?? 1,
5005
+ weekCount
5006
+ );
5007
+ return /* @__PURE__ */ jsxs31(
5008
+ "div",
5009
+ {
5010
+ className: "grid items-center border-b border-[var(--s-border-subtle,#2A2622)] bg-[var(--s-surface-page,#0A0908)]",
5011
+ style: { gridTemplateColumns: trackTemplate },
5012
+ children: [
5013
+ /* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-2 py-2 pl-10 pr-4", children: [
5014
+ /* @__PURE__ */ jsx63(StatusDot, { done: m.done, color: dot }),
5015
+ /* @__PURE__ */ jsx63(
5016
+ "span",
5017
+ {
5018
+ className: cn(
5019
+ "min-w-0 flex-1 truncate text-[13px]",
5020
+ m.done ? "text-[var(--s-ink-muted,#7D7568)] line-through" : "text-[var(--s-ink-secondary,#C9C0B4)]"
5021
+ ),
5022
+ children: m.title
5023
+ }
5024
+ ),
5025
+ m.points != null && /* @__PURE__ */ jsx63("span", { className: "shrink-0 font-[var(--s-font-mono,monospace)] text-[10px] tabular-nums text-[var(--s-ink-muted,#7D7568)]", children: m.points })
5026
+ ] }),
5027
+ /* @__PURE__ */ jsx63(
5028
+ "div",
5029
+ {
5030
+ className: "relative h-6",
5031
+ style: {
5032
+ gridColumn: `${1 + mCol.start} / span ${mCol.span}`
5033
+ },
5034
+ children: /* @__PURE__ */ jsx63(
5035
+ "div",
5036
+ {
5037
+ className: cn(
5038
+ "absolute inset-y-1.5 inset-x-1 rounded-[var(--p-radius-sm,4px)]",
5039
+ m.done ? "" : "border"
5040
+ ),
5041
+ style: m.done ? { background: dot } : {
5042
+ background: tint(dot, 0.08),
5043
+ borderColor: tint(dot, 0.4)
5044
+ }
5045
+ }
5046
+ )
5047
+ }
5048
+ )
5049
+ ]
5050
+ },
5051
+ m.id
5052
+ );
5053
+ })
5054
+ ] }, stage.id);
5055
+ }),
5056
+ stages.length === 0 && /* @__PURE__ */ jsx63("div", { className: "px-4 py-8 text-center text-[13px] text-[var(--s-ink-muted,#7D7568)]", children: "No stages yet." })
5057
+ ] }) }),
5058
+ /* @__PURE__ */ jsxs31("div", { className: "flex flex-wrap items-center gap-4 border-t border-[var(--s-border-subtle,#2A2622)] px-5 py-2.5 font-[var(--s-font-mono,monospace)] text-[10.5px] uppercase tracking-[0.6px] text-[var(--s-ink-muted,#7D7568)]", children: [
5059
+ /* @__PURE__ */ jsx63(LegendItem, { swatch: /* @__PURE__ */ jsx63("span", { className: "h-2.5 w-3 rounded-[2px]", style: { background: "var(--s-brand-solid, #E07A4A)" } }), label: "Completed" }),
5060
+ /* @__PURE__ */ jsx63(LegendItem, { swatch: /* @__PURE__ */ jsx63("span", { className: "h-2.5 w-3 rounded-[2px] border", style: { background: "rgba(224,122,74,0.08)", borderColor: "rgba(224,122,74,0.4)" } }), label: "Upcoming" }),
5061
+ dependencies.length > 0 && /* @__PURE__ */ jsx63(LegendItem, { swatch: /* @__PURE__ */ jsx63("span", { className: "block h-0.5 w-4", style: { background: "var(--s-brand-solid, #E07A4A)", opacity: 0.7 } }), label: "Depends on" })
5062
+ ] })
5063
+ ]
5064
+ }
5065
+ );
5066
+ }
5067
+ function Chevron({ open }) {
5068
+ return /* @__PURE__ */ jsx63(
5069
+ "svg",
5070
+ {
5071
+ width: "14",
5072
+ height: "14",
5073
+ viewBox: "0 0 24 24",
5074
+ fill: "none",
5075
+ stroke: "currentColor",
5076
+ strokeWidth: "1.5",
5077
+ strokeLinecap: "round",
5078
+ strokeLinejoin: "round",
5079
+ className: "shrink-0 text-[var(--s-ink-muted,#7D7568)] transition-transform",
5080
+ style: { transform: open ? "rotate(90deg)" : "none" },
5081
+ "aria-hidden": "true",
5082
+ children: /* @__PURE__ */ jsx63("path", { d: "M9 18l6-6-6-6" })
5083
+ }
5084
+ );
5085
+ }
5086
+ function StatusDot({ done, color }) {
5087
+ if (done) {
5088
+ return /* @__PURE__ */ jsxs31("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
5089
+ /* @__PURE__ */ jsx63("circle", { cx: "12", cy: "12", r: "9", fill: color }),
5090
+ /* @__PURE__ */ jsx63(
5091
+ "path",
5092
+ {
5093
+ d: "M8 12l3 3 5-6",
5094
+ fill: "none",
5095
+ stroke: "var(--s-ink-inverse, #0A0908)",
5096
+ strokeWidth: "2",
5097
+ strokeLinecap: "round",
5098
+ strokeLinejoin: "round"
5099
+ }
5100
+ )
5101
+ ] });
5102
+ }
5103
+ return /* @__PURE__ */ jsx63("svg", { width: "14", height: "14", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx63(
5104
+ "circle",
5105
+ {
5106
+ cx: "12",
5107
+ cy: "12",
5108
+ r: "8",
5109
+ fill: "none",
5110
+ stroke: "var(--s-border-strong, #3A3530)",
5111
+ strokeWidth: "2"
5112
+ }
5113
+ ) });
5114
+ }
5115
+ function LegendItem({ swatch, label }) {
5116
+ return /* @__PURE__ */ jsxs31("span", { className: "flex items-center gap-1.5", children: [
5117
+ swatch,
5118
+ label
5119
+ ] });
5120
+ }
5121
+ function tint(color, alpha) {
5122
+ const hex = /^#([0-9a-f]{6})$/i.exec(color.trim());
5123
+ if (hex) {
5124
+ const n = parseInt(hex[1], 16);
5125
+ const r = n >> 16 & 255;
5126
+ const g = n >> 8 & 255;
5127
+ const b = n & 255;
5128
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
5129
+ }
5130
+ return `color-mix(in srgb, ${color} ${Math.round(alpha * 100)}%, transparent)`;
5131
+ }
5132
+
5133
+ // src/components/organisms/PublishDrawer.tsx
5134
+ import * as React45 from "react";
5135
+ import { Loader2, Youtube, Image as ImageIcon, CheckCircle2, AlertCircle } from "lucide-react";
5136
+ import { jsx as jsx64, jsxs as jsxs32 } from "react/jsx-runtime";
4758
5137
  function parseTags(raw) {
4759
5138
  return raw.split(/[,\n]/).map((t) => t.trim()).filter((t) => t.length > 0);
4760
5139
  }
@@ -4790,16 +5169,16 @@ function PublishDrawer({
4790
5169
  onError,
4791
5170
  className
4792
5171
  }) {
4793
- const [title, setTitle] = React44.useState(suggestedTitle);
4794
- const [description, setDescription] = React44.useState(suggestedDescription);
4795
- const [tagsRaw, setTagsRaw] = React44.useState("");
4796
- const [thumbnailUrl, setThumbnailUrl] = React44.useState(suggestedThumbnailUrl);
4797
- const [accounts, setAccounts] = React44.useState([]);
4798
- const [accountId, setAccountId] = React44.useState(null);
4799
- const [status, setStatus] = React44.useState("idle");
4800
- const [errorMsg, setErrorMsg] = React44.useState(null);
4801
- const [result, setResult] = React44.useState(null);
4802
- React44.useEffect(() => {
5172
+ const [title, setTitle] = React45.useState(suggestedTitle);
5173
+ const [description, setDescription] = React45.useState(suggestedDescription);
5174
+ const [tagsRaw, setTagsRaw] = React45.useState("");
5175
+ const [thumbnailUrl, setThumbnailUrl] = React45.useState(suggestedThumbnailUrl);
5176
+ const [accounts, setAccounts] = React45.useState([]);
5177
+ const [accountId, setAccountId] = React45.useState(null);
5178
+ const [status, setStatus] = React45.useState("idle");
5179
+ const [errorMsg, setErrorMsg] = React45.useState(null);
5180
+ const [result, setResult] = React45.useState(null);
5181
+ React45.useEffect(() => {
4803
5182
  if (open) {
4804
5183
  setTitle(suggestedTitle);
4805
5184
  setDescription(suggestedDescription);
@@ -4809,7 +5188,7 @@ function PublishDrawer({
4809
5188
  setResult(null);
4810
5189
  }
4811
5190
  }, [open]);
4812
- React44.useEffect(() => {
5191
+ React45.useEffect(() => {
4813
5192
  if (!open) return;
4814
5193
  let cancelled = false;
4815
5194
  (async () => {
@@ -4833,7 +5212,7 @@ function PublishDrawer({
4833
5212
  cancelled = true;
4834
5213
  };
4835
5214
  }, [open, supabase]);
4836
- const fail = React44.useCallback(
5215
+ const fail = React45.useCallback(
4837
5216
  (msg) => {
4838
5217
  setStatus("error");
4839
5218
  setErrorMsg(msg);
@@ -4935,18 +5314,18 @@ function PublishDrawer({
4935
5314
  onPublished?.(publishResult);
4936
5315
  }
4937
5316
  const busy = status === "publishing" || status === "rendering-thumb" || status === "loading-accounts";
4938
- return /* @__PURE__ */ jsx63(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs31(SheetContent, { side: "right", className: cn("flex w-full flex-col gap-4 overflow-y-auto sm:max-w-md", className), children: [
4939
- /* @__PURE__ */ jsxs31(SheetHeader, { children: [
4940
- /* @__PURE__ */ jsxs31(SheetTitle, { className: "flex items-center gap-2", children: [
4941
- /* @__PURE__ */ jsx63(Youtube, { className: "h-5 w-5 text-red-600" }),
5317
+ return /* @__PURE__ */ jsx64(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs32(SheetContent, { side: "right", className: cn("flex w-full flex-col gap-4 overflow-y-auto sm:max-w-md", className), children: [
5318
+ /* @__PURE__ */ jsxs32(SheetHeader, { children: [
5319
+ /* @__PURE__ */ jsxs32(SheetTitle, { className: "flex items-center gap-2", children: [
5320
+ /* @__PURE__ */ jsx64(Youtube, { className: "h-5 w-5 text-red-600" }),
4942
5321
  "Publicar no YouTube"
4943
5322
  ] }),
4944
- /* @__PURE__ */ jsx63(SheetDescription, { children: "Publique o v\xEDdeo gravado cross-platform via Zernio. Preencha t\xEDtulo, descri\xE7\xE3o e palavras-chave manualmente." })
5323
+ /* @__PURE__ */ jsx64(SheetDescription, { children: "Publique o v\xEDdeo gravado cross-platform via Zernio. Preencha t\xEDtulo, descri\xE7\xE3o e palavras-chave manualmente." })
4945
5324
  ] }),
4946
- status === "done" && result ? /* @__PURE__ */ jsxs31("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-center", children: [
4947
- /* @__PURE__ */ jsx63(CheckCircle2, { className: "h-10 w-10 text-green-600" }),
4948
- /* @__PURE__ */ jsx63("p", { className: "font-medium", children: "V\xEDdeo publicado!" }),
4949
- result.post_url && /* @__PURE__ */ jsx63(
5325
+ status === "done" && result ? /* @__PURE__ */ jsxs32("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-center", children: [
5326
+ /* @__PURE__ */ jsx64(CheckCircle2, { className: "h-10 w-10 text-green-600" }),
5327
+ /* @__PURE__ */ jsx64("p", { className: "font-medium", children: "V\xEDdeo publicado!" }),
5328
+ result.post_url && /* @__PURE__ */ jsx64(
4950
5329
  "a",
4951
5330
  {
4952
5331
  href: result.post_url,
@@ -4956,15 +5335,15 @@ function PublishDrawer({
4956
5335
  children: "Abrir no YouTube"
4957
5336
  }
4958
5337
  ),
4959
- /* @__PURE__ */ jsxs31("p", { className: "text-xs text-muted-foreground", children: [
5338
+ /* @__PURE__ */ jsxs32("p", { className: "text-xs text-muted-foreground", children: [
4960
5339
  "Zernio post id: ",
4961
5340
  result.zernio_post_id
4962
5341
  ] }),
4963
- /* @__PURE__ */ jsx63(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Fechar" })
4964
- ] }) : /* @__PURE__ */ jsxs31("div", { className: "flex flex-1 flex-col gap-4", children: [
4965
- /* @__PURE__ */ jsxs31("div", { className: "grid gap-2", children: [
4966
- /* @__PURE__ */ jsx63(Label3, { htmlFor: "pd-title", children: "T\xEDtulo" }),
4967
- /* @__PURE__ */ jsx63(
5342
+ /* @__PURE__ */ jsx64(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Fechar" })
5343
+ ] }) : /* @__PURE__ */ jsxs32("div", { className: "flex flex-1 flex-col gap-4", children: [
5344
+ /* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
5345
+ /* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-title", children: "T\xEDtulo" }),
5346
+ /* @__PURE__ */ jsx64(
4968
5347
  Input,
4969
5348
  {
4970
5349
  id: "pd-title",
@@ -4975,9 +5354,9 @@ function PublishDrawer({
4975
5354
  }
4976
5355
  )
4977
5356
  ] }),
4978
- /* @__PURE__ */ jsxs31("div", { className: "grid gap-2", children: [
4979
- /* @__PURE__ */ jsx63(Label3, { htmlFor: "pd-desc", children: "Descri\xE7\xE3o" }),
4980
- /* @__PURE__ */ jsx63(
5357
+ /* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
5358
+ /* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-desc", children: "Descri\xE7\xE3o" }),
5359
+ /* @__PURE__ */ jsx64(
4981
5360
  Textarea,
4982
5361
  {
4983
5362
  id: "pd-desc",
@@ -4989,9 +5368,9 @@ function PublishDrawer({
4989
5368
  }
4990
5369
  )
4991
5370
  ] }),
4992
- /* @__PURE__ */ jsxs31("div", { className: "grid gap-2", children: [
4993
- /* @__PURE__ */ jsx63(Label3, { htmlFor: "pd-tags", children: "Palavras-chave / tags" }),
4994
- /* @__PURE__ */ jsx63(
5371
+ /* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
5372
+ /* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-tags", children: "Palavras-chave / tags" }),
5373
+ /* @__PURE__ */ jsx64(
4995
5374
  Input,
4996
5375
  {
4997
5376
  id: "pd-tags",
@@ -5001,11 +5380,11 @@ function PublishDrawer({
5001
5380
  disabled: busy
5002
5381
  }
5003
5382
  ),
5004
- /* @__PURE__ */ jsx63("p", { className: "text-xs text-muted-foreground", children: "Separadas por v\xEDrgula. A primeira vira a keyword." })
5383
+ /* @__PURE__ */ jsx64("p", { className: "text-xs text-muted-foreground", children: "Separadas por v\xEDrgula. A primeira vira a keyword." })
5005
5384
  ] }),
5006
- /* @__PURE__ */ jsxs31("div", { className: "grid gap-2", children: [
5007
- /* @__PURE__ */ jsx63(Label3, { htmlFor: "pd-thumb", children: "Thumbnail" }),
5008
- /* @__PURE__ */ jsx63(
5385
+ /* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
5386
+ /* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-thumb", children: "Thumbnail" }),
5387
+ /* @__PURE__ */ jsx64(
5009
5388
  Input,
5010
5389
  {
5011
5390
  id: "pd-thumb",
@@ -5015,7 +5394,7 @@ function PublishDrawer({
5015
5394
  disabled: busy
5016
5395
  }
5017
5396
  ),
5018
- thumbnailTemplateId && /* @__PURE__ */ jsxs31(
5397
+ thumbnailTemplateId && /* @__PURE__ */ jsxs32(
5019
5398
  Button,
5020
5399
  {
5021
5400
  type: "button",
@@ -5025,12 +5404,12 @@ function PublishDrawer({
5025
5404
  disabled: busy,
5026
5405
  className: "w-fit",
5027
5406
  children: [
5028
- status === "rendering-thumb" ? /* @__PURE__ */ jsx63(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx63(ImageIcon, { className: "mr-2 h-4 w-4" }),
5407
+ status === "rendering-thumb" ? /* @__PURE__ */ jsx64(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx64(ImageIcon, { className: "mr-2 h-4 w-4" }),
5029
5408
  "Gerar via Thumbify"
5030
5409
  ]
5031
5410
  }
5032
5411
  ),
5033
- thumbnailUrl && /* @__PURE__ */ jsx63(
5412
+ thumbnailUrl && /* @__PURE__ */ jsx64(
5034
5413
  "img",
5035
5414
  {
5036
5415
  src: thumbnailUrl,
@@ -5039,26 +5418,26 @@ function PublishDrawer({
5039
5418
  }
5040
5419
  )
5041
5420
  ] }),
5042
- /* @__PURE__ */ jsxs31("div", { className: "grid gap-2", children: [
5043
- /* @__PURE__ */ jsx63(Label3, { htmlFor: "pd-account", children: "Canal do YouTube" }),
5044
- /* @__PURE__ */ jsxs31(Select, { value: accountId ?? void 0, onValueChange: setAccountId, disabled: busy || accounts.length === 0, children: [
5045
- /* @__PURE__ */ jsx63(SelectTrigger, { id: "pd-account", children: /* @__PURE__ */ jsx63(
5421
+ /* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
5422
+ /* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-account", children: "Canal do YouTube" }),
5423
+ /* @__PURE__ */ jsxs32(Select, { value: accountId ?? void 0, onValueChange: setAccountId, disabled: busy || accounts.length === 0, children: [
5424
+ /* @__PURE__ */ jsx64(SelectTrigger, { id: "pd-account", children: /* @__PURE__ */ jsx64(
5046
5425
  SelectValue,
5047
5426
  {
5048
5427
  placeholder: status === "loading-accounts" ? "Carregando canais\u2026" : accounts.length === 0 ? "Nenhum canal conectado" : "Selecione um canal"
5049
5428
  }
5050
5429
  ) }),
5051
- /* @__PURE__ */ jsx63(SelectContent, { children: accounts.map((a) => /* @__PURE__ */ jsx63(SelectItem, { value: a.account_id, children: a.account_name ?? a.account_id }, a.id)) })
5430
+ /* @__PURE__ */ jsx64(SelectContent, { children: accounts.map((a) => /* @__PURE__ */ jsx64(SelectItem, { value: a.account_id, children: a.account_name ?? a.account_id }, a.id)) })
5052
5431
  ] })
5053
5432
  ] }),
5054
- errorMsg && /* @__PURE__ */ jsxs31("p", { className: "flex items-center gap-2 text-sm text-destructive", children: [
5055
- /* @__PURE__ */ jsx63(AlertCircle, { className: "h-4 w-4" }),
5433
+ errorMsg && /* @__PURE__ */ jsxs32("p", { className: "flex items-center gap-2 text-sm text-destructive", children: [
5434
+ /* @__PURE__ */ jsx64(AlertCircle, { className: "h-4 w-4" }),
5056
5435
  errorMsg
5057
5436
  ] }),
5058
- /* @__PURE__ */ jsxs31(SheetFooter, { className: "mt-auto", children: [
5059
- /* @__PURE__ */ jsx63(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: busy, children: "Cancelar" }),
5060
- /* @__PURE__ */ jsxs31(Button, { onClick: handlePublish, disabled: busy, children: [
5061
- status === "publishing" && /* @__PURE__ */ jsx63(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
5437
+ /* @__PURE__ */ jsxs32(SheetFooter, { className: "mt-auto", children: [
5438
+ /* @__PURE__ */ jsx64(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: busy, children: "Cancelar" }),
5439
+ /* @__PURE__ */ jsxs32(Button, { onClick: handlePublish, disabled: busy, children: [
5440
+ status === "publishing" && /* @__PURE__ */ jsx64(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
5062
5441
  "Publicar"
5063
5442
  ] })
5064
5443
  ] })
@@ -5074,9 +5453,9 @@ function useIframeAuth() {
5074
5453
  }
5075
5454
 
5076
5455
  // src/hooks/use-iframe-navigate.ts
5077
- import { useCallback as useCallback7 } from "react";
5456
+ import { useCallback as useCallback8 } from "react";
5078
5457
  function useIframeNavigate() {
5079
- return useCallback7((path) => {
5458
+ return useCallback8((path) => {
5080
5459
  if (!window.parent || window.parent === window) return;
5081
5460
  window.parent.postMessage(
5082
5461
  { type: "DFL_NAVIGATE", path },
@@ -5091,7 +5470,7 @@ import {
5091
5470
  useContext as useContext9,
5092
5471
  useMemo as useMemo5
5093
5472
  } from "react";
5094
- import { jsx as jsx64 } from "react/jsx-runtime";
5473
+ import { jsx as jsx65 } from "react/jsx-runtime";
5095
5474
  var FeatureFlagContext = createContext8({
5096
5475
  flags: {},
5097
5476
  isEnabled: () => false
@@ -5107,7 +5486,7 @@ var FeatureFlagProvider = ({
5107
5486
  }),
5108
5487
  [flags]
5109
5488
  );
5110
- return /* @__PURE__ */ jsx64(FeatureFlagContext.Provider, { value, children });
5489
+ return /* @__PURE__ */ jsx65(FeatureFlagContext.Provider, { value, children });
5111
5490
  };
5112
5491
  var useFeatureFlag = (flag) => {
5113
5492
  const { isEnabled } = useContext9(FeatureFlagContext);
@@ -5244,6 +5623,7 @@ export {
5244
5623
  FormItem,
5245
5624
  FormLabel,
5246
5625
  FormMessage,
5626
+ Gantt,
5247
5627
  HoverCard,
5248
5628
  HoverCardContent,
5249
5629
  HoverCardTrigger,
@@ -5384,7 +5764,9 @@ export {
5384
5764
  UserAvatar,
5385
5765
  UserMenu,
5386
5766
  badgeVariants,
5767
+ barGridColumn,
5387
5768
  buttonVariants,
5769
+ clampPct,
5388
5770
  cn,
5389
5771
  filterPublishableAccounts,
5390
5772
  getInitials,
@@ -5396,6 +5778,9 @@ export {
5396
5778
  memberHueVar,
5397
5779
  navigationMenuTriggerStyle,
5398
5780
  parseTags,
5781
+ resolveWeekCount,
5782
+ resolveWeekLabels,
5783
+ stageProgress,
5399
5784
  toast,
5400
5785
  toggleVariants,
5401
5786
  useAuth,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devfellowship/components",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "DFL Design System — UI components, hooks, utils and providers",
5
5
  "type": "module",
6
6
  "sideEffects": [