@devfellowship/components 1.2.2 → 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/cli.js +737 -0
- package/dist/index.cjs +446 -55
- package/dist/index.d.cts +73 -1
- package/dist/index.d.ts +73 -1
- package/dist/index.js +442 -57
- package/package.json +21 -3
package/dist/index.js
CHANGED
|
@@ -4751,10 +4751,389 @@ function AppNavbar({
|
|
|
4751
4751
|
);
|
|
4752
4752
|
}
|
|
4753
4753
|
|
|
4754
|
-
// src/components/organisms/
|
|
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] =
|
|
4794
|
-
const [description, setDescription] =
|
|
4795
|
-
const [tagsRaw, setTagsRaw] =
|
|
4796
|
-
const [thumbnailUrl, setThumbnailUrl] =
|
|
4797
|
-
const [accounts, setAccounts] =
|
|
4798
|
-
const [accountId, setAccountId] =
|
|
4799
|
-
const [status, setStatus] =
|
|
4800
|
-
const [errorMsg, setErrorMsg] =
|
|
4801
|
-
const [result, setResult] =
|
|
4802
|
-
|
|
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
|
-
|
|
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 =
|
|
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__ */
|
|
4939
|
-
/* @__PURE__ */
|
|
4940
|
-
/* @__PURE__ */
|
|
4941
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4947
|
-
/* @__PURE__ */
|
|
4948
|
-
/* @__PURE__ */
|
|
4949
|
-
result.post_url && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4964
|
-
] }) : /* @__PURE__ */
|
|
4965
|
-
/* @__PURE__ */
|
|
4966
|
-
/* @__PURE__ */
|
|
4967
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4979
|
-
/* @__PURE__ */
|
|
4980
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4993
|
-
/* @__PURE__ */
|
|
4994
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5383
|
+
/* @__PURE__ */ jsx64("p", { className: "text-xs text-muted-foreground", children: "Separadas por v\xEDrgula. A primeira vira a keyword." })
|
|
5005
5384
|
] }),
|
|
5006
|
-
/* @__PURE__ */
|
|
5007
|
-
/* @__PURE__ */
|
|
5008
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
5043
|
-
/* @__PURE__ */
|
|
5044
|
-
/* @__PURE__ */
|
|
5045
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
5055
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5059
|
-
/* @__PURE__ */
|
|
5060
|
-
/* @__PURE__ */
|
|
5061
|
-
status === "publishing" && /* @__PURE__ */
|
|
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
|
|
5456
|
+
import { useCallback as useCallback8 } from "react";
|
|
5078
5457
|
function useIframeNavigate() {
|
|
5079
|
-
return
|
|
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
|
|
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__ */
|
|
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,
|