@devfellowship/components 1.2.3 → 1.4.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.cjs +495 -55
- package/dist/index.d.cts +87 -1
- package/dist/index.d.ts +87 -1
- package/dist/index.js +489 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4751,10 +4751,434 @@ 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
|
+
var DEFAULT_NAME_COL_WIDTH = 320;
|
|
4758
|
+
function resolveNameColWidth(nameColWidth, labelWidth) {
|
|
4759
|
+
if (typeof nameColWidth === "number" && nameColWidth > 0) return Math.round(nameColWidth);
|
|
4760
|
+
if (typeof labelWidth === "number" && labelWidth > 0) return Math.round(labelWidth);
|
|
4761
|
+
return DEFAULT_NAME_COL_WIDTH;
|
|
4762
|
+
}
|
|
4763
|
+
function clampPct(value) {
|
|
4764
|
+
if (value == null || Number.isNaN(value)) return 0;
|
|
4765
|
+
return Math.max(0, Math.min(100, Math.round(value)));
|
|
4766
|
+
}
|
|
4767
|
+
function stageProgress(stage) {
|
|
4768
|
+
if (stage.progress != null) return clampPct(stage.progress);
|
|
4769
|
+
const ms = stage.milestones ?? [];
|
|
4770
|
+
if (ms.length === 0) return 0;
|
|
4771
|
+
const done = ms.filter((m) => m.done).length;
|
|
4772
|
+
return clampPct(done / ms.length * 100);
|
|
4773
|
+
}
|
|
4774
|
+
function resolveWeekCount(stages, weeks) {
|
|
4775
|
+
if (Array.isArray(weeks)) return Math.max(1, weeks.length);
|
|
4776
|
+
if (typeof weeks === "number" && weeks > 0) return Math.round(weeks);
|
|
4777
|
+
let max = 1;
|
|
4778
|
+
for (const s of stages) {
|
|
4779
|
+
max = Math.max(max, s.weekStart + Math.max(1, s.weekSpan) - 1);
|
|
4780
|
+
for (const m of s.milestones ?? []) {
|
|
4781
|
+
const ws = m.weekStart ?? s.weekStart;
|
|
4782
|
+
max = Math.max(max, ws + Math.max(1, m.weekSpan ?? 1) - 1);
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4785
|
+
return Math.max(1, max);
|
|
4786
|
+
}
|
|
4787
|
+
function resolveWeekLabels(count2, weeks) {
|
|
4788
|
+
if (Array.isArray(weeks)) return weeks;
|
|
4789
|
+
return Array.from({ length: count2 }, (_, i) => `W${i + 1}`);
|
|
4790
|
+
}
|
|
4791
|
+
function barGridColumn(weekStart, weekSpan, weekCount) {
|
|
4792
|
+
const start = Math.max(1, Math.min(weekStart, weekCount));
|
|
4793
|
+
const rawEnd = start + Math.max(1, weekSpan) - 1;
|
|
4794
|
+
const end = Math.max(start, Math.min(rawEnd, weekCount));
|
|
4795
|
+
return { start, span: end - start + 1 };
|
|
4796
|
+
}
|
|
4797
|
+
var DEFAULT_DOT = "var(--s-brand-solid, #E07A4A)";
|
|
4798
|
+
function Gantt({
|
|
4799
|
+
stages,
|
|
4800
|
+
weeks,
|
|
4801
|
+
dependencies = [],
|
|
4802
|
+
rowsHeader = "Stage / Task",
|
|
4803
|
+
stagesOnly = false,
|
|
4804
|
+
header,
|
|
4805
|
+
labelWidth,
|
|
4806
|
+
nameColWidth,
|
|
4807
|
+
weekMinWidth = 64,
|
|
4808
|
+
className,
|
|
4809
|
+
style,
|
|
4810
|
+
...rest
|
|
4811
|
+
}) {
|
|
4812
|
+
const weekCount = resolveWeekCount(stages, weeks);
|
|
4813
|
+
const weekLabels = resolveWeekLabels(weekCount, weeks);
|
|
4814
|
+
const nameWidth = resolveNameColWidth(nameColWidth, labelWidth);
|
|
4815
|
+
const [collapsed, setCollapsed] = React44.useState(
|
|
4816
|
+
() => Object.fromEntries(stages.filter((s) => s.collapsed).map((s) => [s.id, true]))
|
|
4817
|
+
);
|
|
4818
|
+
const toggle = (id) => setCollapsed((c) => ({ ...c, [id]: !c[id] }));
|
|
4819
|
+
const gridRef = React44.useRef(null);
|
|
4820
|
+
const barRefs = React44.useRef({});
|
|
4821
|
+
const [edges, setEdges] = React44.useState([]);
|
|
4822
|
+
const recomputeEdges = React44.useCallback(() => {
|
|
4823
|
+
const root = gridRef.current;
|
|
4824
|
+
if (!root || dependencies.length === 0) {
|
|
4825
|
+
setEdges([]);
|
|
4826
|
+
return;
|
|
4827
|
+
}
|
|
4828
|
+
const rootBox = root.getBoundingClientRect();
|
|
4829
|
+
const next = [];
|
|
4830
|
+
for (const dep of dependencies) {
|
|
4831
|
+
const a = barRefs.current[dep.from];
|
|
4832
|
+
const b = barRefs.current[dep.to];
|
|
4833
|
+
if (!a || !b) continue;
|
|
4834
|
+
const ab = a.getBoundingClientRect();
|
|
4835
|
+
const bb = b.getBoundingClientRect();
|
|
4836
|
+
next.push({
|
|
4837
|
+
id: `${dep.from}->${dep.to}`,
|
|
4838
|
+
x1: ab.right - rootBox.left,
|
|
4839
|
+
y1: ab.top - rootBox.top + ab.height / 2,
|
|
4840
|
+
x2: bb.left - rootBox.left,
|
|
4841
|
+
y2: bb.top - rootBox.top + bb.height / 2
|
|
4842
|
+
});
|
|
4843
|
+
}
|
|
4844
|
+
setEdges(next);
|
|
4845
|
+
}, [dependencies]);
|
|
4846
|
+
React44.useLayoutEffect(() => {
|
|
4847
|
+
recomputeEdges();
|
|
4848
|
+
}, [recomputeEdges, collapsed, weekCount, stages]);
|
|
4849
|
+
React44.useEffect(() => {
|
|
4850
|
+
if (dependencies.length === 0) return;
|
|
4851
|
+
const handler = () => recomputeEdges();
|
|
4852
|
+
window.addEventListener("resize", handler);
|
|
4853
|
+
return () => window.removeEventListener("resize", handler);
|
|
4854
|
+
}, [dependencies.length, recomputeEdges]);
|
|
4855
|
+
const trackTemplate = `${nameWidth}px repeat(${weekCount}, minmax(${weekMinWidth}px, 1fr))`;
|
|
4856
|
+
const stickyCol = "sticky left-0 z-20 after:absolute after:inset-y-0 after:right-0 after:w-px after:bg-[var(--s-border-subtle,#2A2622)]";
|
|
4857
|
+
return /* @__PURE__ */ jsxs31(
|
|
4858
|
+
"div",
|
|
4859
|
+
{
|
|
4860
|
+
className: cn(
|
|
4861
|
+
"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",
|
|
4862
|
+
className
|
|
4863
|
+
),
|
|
4864
|
+
style,
|
|
4865
|
+
...rest,
|
|
4866
|
+
children: [
|
|
4867
|
+
header && /* @__PURE__ */ jsx63("div", { className: "border-b border-[var(--s-border-subtle,#2A2622)] px-5 py-4", children: header }),
|
|
4868
|
+
/* @__PURE__ */ jsx63("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs31("div", { ref: gridRef, className: "relative min-w-max", children: [
|
|
4869
|
+
edges.length > 0 && /* @__PURE__ */ jsxs31(
|
|
4870
|
+
"svg",
|
|
4871
|
+
{
|
|
4872
|
+
className: "pointer-events-none absolute inset-0 h-full w-full",
|
|
4873
|
+
"aria-hidden": "true",
|
|
4874
|
+
children: [
|
|
4875
|
+
/* @__PURE__ */ jsx63("defs", { children: /* @__PURE__ */ jsx63(
|
|
4876
|
+
"marker",
|
|
4877
|
+
{
|
|
4878
|
+
id: "dfl-gantt-arrow",
|
|
4879
|
+
markerWidth: "7",
|
|
4880
|
+
markerHeight: "7",
|
|
4881
|
+
refX: "5",
|
|
4882
|
+
refY: "3",
|
|
4883
|
+
orient: "auto",
|
|
4884
|
+
children: /* @__PURE__ */ jsx63(
|
|
4885
|
+
"path",
|
|
4886
|
+
{
|
|
4887
|
+
d: "M0,0 L6,3 L0,6 Z",
|
|
4888
|
+
fill: "var(--s-brand-solid, #E07A4A)"
|
|
4889
|
+
}
|
|
4890
|
+
)
|
|
4891
|
+
}
|
|
4892
|
+
) }),
|
|
4893
|
+
edges.map((e) => {
|
|
4894
|
+
const stub = 14;
|
|
4895
|
+
const c1x = e.x1 + stub;
|
|
4896
|
+
const c2x = e.x2 - stub;
|
|
4897
|
+
return /* @__PURE__ */ jsx63(
|
|
4898
|
+
"path",
|
|
4899
|
+
{
|
|
4900
|
+
d: `M ${e.x1} ${e.y1} C ${c1x} ${e.y1}, ${c2x} ${e.y2}, ${e.x2} ${e.y2}`,
|
|
4901
|
+
fill: "none",
|
|
4902
|
+
stroke: "var(--s-brand-solid, #E07A4A)",
|
|
4903
|
+
strokeWidth: 1.5,
|
|
4904
|
+
strokeOpacity: 0.65,
|
|
4905
|
+
markerEnd: "url(#dfl-gantt-arrow)"
|
|
4906
|
+
},
|
|
4907
|
+
e.id
|
|
4908
|
+
);
|
|
4909
|
+
})
|
|
4910
|
+
]
|
|
4911
|
+
}
|
|
4912
|
+
),
|
|
4913
|
+
/* @__PURE__ */ jsxs31(
|
|
4914
|
+
"div",
|
|
4915
|
+
{
|
|
4916
|
+
className: "grid items-center border-b border-[var(--s-border-subtle,#2A2622)] bg-[var(--s-surface-raised,#1A1714)]",
|
|
4917
|
+
style: { gridTemplateColumns: trackTemplate },
|
|
4918
|
+
children: [
|
|
4919
|
+
/* @__PURE__ */ jsx63(
|
|
4920
|
+
"div",
|
|
4921
|
+
{
|
|
4922
|
+
className: cn(
|
|
4923
|
+
stickyCol,
|
|
4924
|
+
"bg-[var(--s-surface-raised,#1A1714)] 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)]"
|
|
4925
|
+
),
|
|
4926
|
+
children: rowsHeader
|
|
4927
|
+
}
|
|
4928
|
+
),
|
|
4929
|
+
weekLabels.map((label, i) => /* @__PURE__ */ jsx63(
|
|
4930
|
+
"div",
|
|
4931
|
+
{
|
|
4932
|
+
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)]",
|
|
4933
|
+
children: label
|
|
4934
|
+
},
|
|
4935
|
+
i
|
|
4936
|
+
))
|
|
4937
|
+
]
|
|
4938
|
+
}
|
|
4939
|
+
),
|
|
4940
|
+
stages.map((stage) => {
|
|
4941
|
+
const pct = stageProgress(stage);
|
|
4942
|
+
const dot = stage.color || DEFAULT_DOT;
|
|
4943
|
+
const isCollapsed = !!collapsed[stage.id];
|
|
4944
|
+
const ms = stage.milestones ?? [];
|
|
4945
|
+
const done = ms.filter((m) => m.done).length;
|
|
4946
|
+
const sCol = barGridColumn(stage.weekStart, stage.weekSpan, weekCount);
|
|
4947
|
+
return /* @__PURE__ */ jsxs31(React44.Fragment, { children: [
|
|
4948
|
+
/* @__PURE__ */ jsxs31(
|
|
4949
|
+
"div",
|
|
4950
|
+
{
|
|
4951
|
+
className: "grid items-center border-b border-[var(--s-border-subtle,#2A2622)]",
|
|
4952
|
+
style: { gridTemplateColumns: trackTemplate },
|
|
4953
|
+
children: [
|
|
4954
|
+
/* @__PURE__ */ jsxs31(
|
|
4955
|
+
"button",
|
|
4956
|
+
{
|
|
4957
|
+
type: "button",
|
|
4958
|
+
onClick: () => toggle(stage.id),
|
|
4959
|
+
className: cn(
|
|
4960
|
+
stickyCol,
|
|
4961
|
+
"flex items-center gap-2 bg-[var(--s-surface-panel,#141210)] px-4 py-3 text-left transition-colors hover:bg-[var(--s-surface-raised,#1A1714)]"
|
|
4962
|
+
),
|
|
4963
|
+
"aria-expanded": !isCollapsed,
|
|
4964
|
+
children: [
|
|
4965
|
+
/* @__PURE__ */ jsx63(Chevron, { open: !isCollapsed }),
|
|
4966
|
+
/* @__PURE__ */ jsx63(
|
|
4967
|
+
"span",
|
|
4968
|
+
{
|
|
4969
|
+
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
4970
|
+
style: { background: dot }
|
|
4971
|
+
}
|
|
4972
|
+
),
|
|
4973
|
+
/* @__PURE__ */ jsxs31("span", { className: "min-w-0", children: [
|
|
4974
|
+
/* @__PURE__ */ jsx63(
|
|
4975
|
+
"span",
|
|
4976
|
+
{
|
|
4977
|
+
className: "block truncate text-[13px] font-semibold text-[var(--s-ink-primary,#F6F1E7)]",
|
|
4978
|
+
title: stage.title,
|
|
4979
|
+
children: stage.title
|
|
4980
|
+
}
|
|
4981
|
+
),
|
|
4982
|
+
stage.subtitle && /* @__PURE__ */ jsx63(
|
|
4983
|
+
"span",
|
|
4984
|
+
{
|
|
4985
|
+
className: "block truncate text-[11px] text-[var(--s-ink-muted,#7D7568)]",
|
|
4986
|
+
title: stage.subtitle,
|
|
4987
|
+
children: stage.subtitle
|
|
4988
|
+
}
|
|
4989
|
+
)
|
|
4990
|
+
] }),
|
|
4991
|
+
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: [
|
|
4992
|
+
done,
|
|
4993
|
+
"/",
|
|
4994
|
+
ms.length
|
|
4995
|
+
] })
|
|
4996
|
+
]
|
|
4997
|
+
}
|
|
4998
|
+
),
|
|
4999
|
+
/* @__PURE__ */ jsx63(
|
|
5000
|
+
"div",
|
|
5001
|
+
{
|
|
5002
|
+
className: "relative h-9",
|
|
5003
|
+
style: {
|
|
5004
|
+
gridColumn: `${1 + sCol.start} / span ${sCol.span}`
|
|
5005
|
+
},
|
|
5006
|
+
children: /* @__PURE__ */ jsxs31(
|
|
5007
|
+
"div",
|
|
5008
|
+
{
|
|
5009
|
+
ref: (el) => {
|
|
5010
|
+
barRefs.current[stage.id] = el;
|
|
5011
|
+
},
|
|
5012
|
+
className: "absolute inset-y-2 inset-x-1 overflow-hidden rounded-[var(--p-radius-sm,4px)]",
|
|
5013
|
+
style: { background: tint(dot, 0.16) },
|
|
5014
|
+
title: `${stage.title} \xB7 ${pct}%`,
|
|
5015
|
+
children: [
|
|
5016
|
+
/* @__PURE__ */ jsx63(
|
|
5017
|
+
"div",
|
|
5018
|
+
{
|
|
5019
|
+
className: "h-full rounded-[var(--p-radius-sm,4px)]",
|
|
5020
|
+
style: { width: `${pct}%`, background: dot }
|
|
5021
|
+
}
|
|
5022
|
+
),
|
|
5023
|
+
/* @__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: [
|
|
5024
|
+
pct,
|
|
5025
|
+
"%"
|
|
5026
|
+
] })
|
|
5027
|
+
]
|
|
5028
|
+
}
|
|
5029
|
+
)
|
|
5030
|
+
}
|
|
5031
|
+
)
|
|
5032
|
+
]
|
|
5033
|
+
}
|
|
5034
|
+
),
|
|
5035
|
+
!stagesOnly && !isCollapsed && ms.map((m) => {
|
|
5036
|
+
const mStart = m.weekStart ?? stage.weekStart;
|
|
5037
|
+
const mCol = barGridColumn(
|
|
5038
|
+
mStart,
|
|
5039
|
+
m.weekSpan ?? 1,
|
|
5040
|
+
weekCount
|
|
5041
|
+
);
|
|
5042
|
+
return /* @__PURE__ */ jsxs31(
|
|
5043
|
+
"div",
|
|
5044
|
+
{
|
|
5045
|
+
className: "grid items-center border-b border-[var(--s-border-subtle,#2A2622)] bg-[var(--s-surface-page,#0A0908)]",
|
|
5046
|
+
style: { gridTemplateColumns: trackTemplate },
|
|
5047
|
+
children: [
|
|
5048
|
+
/* @__PURE__ */ jsxs31(
|
|
5049
|
+
"div",
|
|
5050
|
+
{
|
|
5051
|
+
className: cn(
|
|
5052
|
+
stickyCol,
|
|
5053
|
+
"flex items-center gap-2 bg-[var(--s-surface-page,#0A0908)] py-2 pl-10 pr-4"
|
|
5054
|
+
),
|
|
5055
|
+
children: [
|
|
5056
|
+
/* @__PURE__ */ jsx63(StatusDot, { done: m.done, color: dot }),
|
|
5057
|
+
/* @__PURE__ */ jsx63(
|
|
5058
|
+
"span",
|
|
5059
|
+
{
|
|
5060
|
+
className: cn(
|
|
5061
|
+
"min-w-0 flex-1 truncate text-[13px]",
|
|
5062
|
+
m.done ? "text-[var(--s-ink-muted,#7D7568)] line-through" : "text-[var(--s-ink-secondary,#C9C0B4)]"
|
|
5063
|
+
),
|
|
5064
|
+
title: m.title,
|
|
5065
|
+
children: m.title
|
|
5066
|
+
}
|
|
5067
|
+
),
|
|
5068
|
+
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 })
|
|
5069
|
+
]
|
|
5070
|
+
}
|
|
5071
|
+
),
|
|
5072
|
+
/* @__PURE__ */ jsx63(
|
|
5073
|
+
"div",
|
|
5074
|
+
{
|
|
5075
|
+
className: "relative h-6",
|
|
5076
|
+
style: {
|
|
5077
|
+
gridColumn: `${1 + mCol.start} / span ${mCol.span}`
|
|
5078
|
+
},
|
|
5079
|
+
children: /* @__PURE__ */ jsx63(
|
|
5080
|
+
"div",
|
|
5081
|
+
{
|
|
5082
|
+
className: cn(
|
|
5083
|
+
"absolute inset-y-1.5 inset-x-1 rounded-[var(--p-radius-sm,4px)]",
|
|
5084
|
+
m.done ? "" : "border"
|
|
5085
|
+
),
|
|
5086
|
+
style: m.done ? { background: dot } : {
|
|
5087
|
+
background: tint(dot, 0.08),
|
|
5088
|
+
borderColor: tint(dot, 0.4)
|
|
5089
|
+
}
|
|
5090
|
+
}
|
|
5091
|
+
)
|
|
5092
|
+
}
|
|
5093
|
+
)
|
|
5094
|
+
]
|
|
5095
|
+
},
|
|
5096
|
+
m.id
|
|
5097
|
+
);
|
|
5098
|
+
})
|
|
5099
|
+
] }, stage.id);
|
|
5100
|
+
}),
|
|
5101
|
+
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." })
|
|
5102
|
+
] }) }),
|
|
5103
|
+
/* @__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: [
|
|
5104
|
+
/* @__PURE__ */ jsx63(LegendItem, { swatch: /* @__PURE__ */ jsx63("span", { className: "h-2.5 w-3 rounded-[2px]", style: { background: "var(--s-brand-solid, #E07A4A)" } }), label: "Completed" }),
|
|
5105
|
+
/* @__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" }),
|
|
5106
|
+
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" })
|
|
5107
|
+
] })
|
|
5108
|
+
]
|
|
5109
|
+
}
|
|
5110
|
+
);
|
|
5111
|
+
}
|
|
5112
|
+
function Chevron({ open }) {
|
|
5113
|
+
return /* @__PURE__ */ jsx63(
|
|
5114
|
+
"svg",
|
|
5115
|
+
{
|
|
5116
|
+
width: "14",
|
|
5117
|
+
height: "14",
|
|
5118
|
+
viewBox: "0 0 24 24",
|
|
5119
|
+
fill: "none",
|
|
5120
|
+
stroke: "currentColor",
|
|
5121
|
+
strokeWidth: "1.5",
|
|
5122
|
+
strokeLinecap: "round",
|
|
5123
|
+
strokeLinejoin: "round",
|
|
5124
|
+
className: "shrink-0 text-[var(--s-ink-muted,#7D7568)] transition-transform",
|
|
5125
|
+
style: { transform: open ? "rotate(90deg)" : "none" },
|
|
5126
|
+
"aria-hidden": "true",
|
|
5127
|
+
children: /* @__PURE__ */ jsx63("path", { d: "M9 18l6-6-6-6" })
|
|
5128
|
+
}
|
|
5129
|
+
);
|
|
5130
|
+
}
|
|
5131
|
+
function StatusDot({ done, color }) {
|
|
5132
|
+
if (done) {
|
|
5133
|
+
return /* @__PURE__ */ jsxs31("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
5134
|
+
/* @__PURE__ */ jsx63("circle", { cx: "12", cy: "12", r: "9", fill: color }),
|
|
5135
|
+
/* @__PURE__ */ jsx63(
|
|
5136
|
+
"path",
|
|
5137
|
+
{
|
|
5138
|
+
d: "M8 12l3 3 5-6",
|
|
5139
|
+
fill: "none",
|
|
5140
|
+
stroke: "var(--s-ink-inverse, #0A0908)",
|
|
5141
|
+
strokeWidth: "2",
|
|
5142
|
+
strokeLinecap: "round",
|
|
5143
|
+
strokeLinejoin: "round"
|
|
5144
|
+
}
|
|
5145
|
+
)
|
|
5146
|
+
] });
|
|
5147
|
+
}
|
|
5148
|
+
return /* @__PURE__ */ jsx63("svg", { width: "14", height: "14", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx63(
|
|
5149
|
+
"circle",
|
|
5150
|
+
{
|
|
5151
|
+
cx: "12",
|
|
5152
|
+
cy: "12",
|
|
5153
|
+
r: "8",
|
|
5154
|
+
fill: "none",
|
|
5155
|
+
stroke: "var(--s-border-strong, #3A3530)",
|
|
5156
|
+
strokeWidth: "2"
|
|
5157
|
+
}
|
|
5158
|
+
) });
|
|
5159
|
+
}
|
|
5160
|
+
function LegendItem({ swatch, label }) {
|
|
5161
|
+
return /* @__PURE__ */ jsxs31("span", { className: "flex items-center gap-1.5", children: [
|
|
5162
|
+
swatch,
|
|
5163
|
+
label
|
|
5164
|
+
] });
|
|
5165
|
+
}
|
|
5166
|
+
function tint(color, alpha) {
|
|
5167
|
+
const hex = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
5168
|
+
if (hex) {
|
|
5169
|
+
const n = parseInt(hex[1], 16);
|
|
5170
|
+
const r = n >> 16 & 255;
|
|
5171
|
+
const g = n >> 8 & 255;
|
|
5172
|
+
const b = n & 255;
|
|
5173
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
5174
|
+
}
|
|
5175
|
+
return `color-mix(in srgb, ${color} ${Math.round(alpha * 100)}%, transparent)`;
|
|
5176
|
+
}
|
|
5177
|
+
|
|
5178
|
+
// src/components/organisms/PublishDrawer.tsx
|
|
5179
|
+
import * as React45 from "react";
|
|
5180
|
+
import { Loader2, Youtube, Image as ImageIcon, CheckCircle2, AlertCircle } from "lucide-react";
|
|
5181
|
+
import { jsx as jsx64, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
4758
5182
|
function parseTags(raw) {
|
|
4759
5183
|
return raw.split(/[,\n]/).map((t) => t.trim()).filter((t) => t.length > 0);
|
|
4760
5184
|
}
|
|
@@ -4790,16 +5214,16 @@ function PublishDrawer({
|
|
|
4790
5214
|
onError,
|
|
4791
5215
|
className
|
|
4792
5216
|
}) {
|
|
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
|
-
|
|
5217
|
+
const [title, setTitle] = React45.useState(suggestedTitle);
|
|
5218
|
+
const [description, setDescription] = React45.useState(suggestedDescription);
|
|
5219
|
+
const [tagsRaw, setTagsRaw] = React45.useState("");
|
|
5220
|
+
const [thumbnailUrl, setThumbnailUrl] = React45.useState(suggestedThumbnailUrl);
|
|
5221
|
+
const [accounts, setAccounts] = React45.useState([]);
|
|
5222
|
+
const [accountId, setAccountId] = React45.useState(null);
|
|
5223
|
+
const [status, setStatus] = React45.useState("idle");
|
|
5224
|
+
const [errorMsg, setErrorMsg] = React45.useState(null);
|
|
5225
|
+
const [result, setResult] = React45.useState(null);
|
|
5226
|
+
React45.useEffect(() => {
|
|
4803
5227
|
if (open) {
|
|
4804
5228
|
setTitle(suggestedTitle);
|
|
4805
5229
|
setDescription(suggestedDescription);
|
|
@@ -4809,7 +5233,7 @@ function PublishDrawer({
|
|
|
4809
5233
|
setResult(null);
|
|
4810
5234
|
}
|
|
4811
5235
|
}, [open]);
|
|
4812
|
-
|
|
5236
|
+
React45.useEffect(() => {
|
|
4813
5237
|
if (!open) return;
|
|
4814
5238
|
let cancelled = false;
|
|
4815
5239
|
(async () => {
|
|
@@ -4833,7 +5257,7 @@ function PublishDrawer({
|
|
|
4833
5257
|
cancelled = true;
|
|
4834
5258
|
};
|
|
4835
5259
|
}, [open, supabase]);
|
|
4836
|
-
const fail =
|
|
5260
|
+
const fail = React45.useCallback(
|
|
4837
5261
|
(msg) => {
|
|
4838
5262
|
setStatus("error");
|
|
4839
5263
|
setErrorMsg(msg);
|
|
@@ -4935,18 +5359,18 @@ function PublishDrawer({
|
|
|
4935
5359
|
onPublished?.(publishResult);
|
|
4936
5360
|
}
|
|
4937
5361
|
const busy = status === "publishing" || status === "rendering-thumb" || status === "loading-accounts";
|
|
4938
|
-
return /* @__PURE__ */
|
|
4939
|
-
/* @__PURE__ */
|
|
4940
|
-
/* @__PURE__ */
|
|
4941
|
-
/* @__PURE__ */
|
|
5362
|
+
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: [
|
|
5363
|
+
/* @__PURE__ */ jsxs32(SheetHeader, { children: [
|
|
5364
|
+
/* @__PURE__ */ jsxs32(SheetTitle, { className: "flex items-center gap-2", children: [
|
|
5365
|
+
/* @__PURE__ */ jsx64(Youtube, { className: "h-5 w-5 text-red-600" }),
|
|
4942
5366
|
"Publicar no YouTube"
|
|
4943
5367
|
] }),
|
|
4944
|
-
/* @__PURE__ */
|
|
5368
|
+
/* @__PURE__ */ jsx64(SheetDescription, { children: "Publique o v\xEDdeo gravado cross-platform via Zernio. Preencha t\xEDtulo, descri\xE7\xE3o e palavras-chave manualmente." })
|
|
4945
5369
|
] }),
|
|
4946
|
-
status === "done" && result ? /* @__PURE__ */
|
|
4947
|
-
/* @__PURE__ */
|
|
4948
|
-
/* @__PURE__ */
|
|
4949
|
-
result.post_url && /* @__PURE__ */
|
|
5370
|
+
status === "done" && result ? /* @__PURE__ */ jsxs32("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-center", children: [
|
|
5371
|
+
/* @__PURE__ */ jsx64(CheckCircle2, { className: "h-10 w-10 text-green-600" }),
|
|
5372
|
+
/* @__PURE__ */ jsx64("p", { className: "font-medium", children: "V\xEDdeo publicado!" }),
|
|
5373
|
+
result.post_url && /* @__PURE__ */ jsx64(
|
|
4950
5374
|
"a",
|
|
4951
5375
|
{
|
|
4952
5376
|
href: result.post_url,
|
|
@@ -4956,15 +5380,15 @@ function PublishDrawer({
|
|
|
4956
5380
|
children: "Abrir no YouTube"
|
|
4957
5381
|
}
|
|
4958
5382
|
),
|
|
4959
|
-
/* @__PURE__ */
|
|
5383
|
+
/* @__PURE__ */ jsxs32("p", { className: "text-xs text-muted-foreground", children: [
|
|
4960
5384
|
"Zernio post id: ",
|
|
4961
5385
|
result.zernio_post_id
|
|
4962
5386
|
] }),
|
|
4963
|
-
/* @__PURE__ */
|
|
4964
|
-
] }) : /* @__PURE__ */
|
|
4965
|
-
/* @__PURE__ */
|
|
4966
|
-
/* @__PURE__ */
|
|
4967
|
-
/* @__PURE__ */
|
|
5387
|
+
/* @__PURE__ */ jsx64(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Fechar" })
|
|
5388
|
+
] }) : /* @__PURE__ */ jsxs32("div", { className: "flex flex-1 flex-col gap-4", children: [
|
|
5389
|
+
/* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
|
|
5390
|
+
/* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-title", children: "T\xEDtulo" }),
|
|
5391
|
+
/* @__PURE__ */ jsx64(
|
|
4968
5392
|
Input,
|
|
4969
5393
|
{
|
|
4970
5394
|
id: "pd-title",
|
|
@@ -4975,9 +5399,9 @@ function PublishDrawer({
|
|
|
4975
5399
|
}
|
|
4976
5400
|
)
|
|
4977
5401
|
] }),
|
|
4978
|
-
/* @__PURE__ */
|
|
4979
|
-
/* @__PURE__ */
|
|
4980
|
-
/* @__PURE__ */
|
|
5402
|
+
/* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
|
|
5403
|
+
/* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-desc", children: "Descri\xE7\xE3o" }),
|
|
5404
|
+
/* @__PURE__ */ jsx64(
|
|
4981
5405
|
Textarea,
|
|
4982
5406
|
{
|
|
4983
5407
|
id: "pd-desc",
|
|
@@ -4989,9 +5413,9 @@ function PublishDrawer({
|
|
|
4989
5413
|
}
|
|
4990
5414
|
)
|
|
4991
5415
|
] }),
|
|
4992
|
-
/* @__PURE__ */
|
|
4993
|
-
/* @__PURE__ */
|
|
4994
|
-
/* @__PURE__ */
|
|
5416
|
+
/* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
|
|
5417
|
+
/* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-tags", children: "Palavras-chave / tags" }),
|
|
5418
|
+
/* @__PURE__ */ jsx64(
|
|
4995
5419
|
Input,
|
|
4996
5420
|
{
|
|
4997
5421
|
id: "pd-tags",
|
|
@@ -5001,11 +5425,11 @@ function PublishDrawer({
|
|
|
5001
5425
|
disabled: busy
|
|
5002
5426
|
}
|
|
5003
5427
|
),
|
|
5004
|
-
/* @__PURE__ */
|
|
5428
|
+
/* @__PURE__ */ jsx64("p", { className: "text-xs text-muted-foreground", children: "Separadas por v\xEDrgula. A primeira vira a keyword." })
|
|
5005
5429
|
] }),
|
|
5006
|
-
/* @__PURE__ */
|
|
5007
|
-
/* @__PURE__ */
|
|
5008
|
-
/* @__PURE__ */
|
|
5430
|
+
/* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
|
|
5431
|
+
/* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-thumb", children: "Thumbnail" }),
|
|
5432
|
+
/* @__PURE__ */ jsx64(
|
|
5009
5433
|
Input,
|
|
5010
5434
|
{
|
|
5011
5435
|
id: "pd-thumb",
|
|
@@ -5015,7 +5439,7 @@ function PublishDrawer({
|
|
|
5015
5439
|
disabled: busy
|
|
5016
5440
|
}
|
|
5017
5441
|
),
|
|
5018
|
-
thumbnailTemplateId && /* @__PURE__ */
|
|
5442
|
+
thumbnailTemplateId && /* @__PURE__ */ jsxs32(
|
|
5019
5443
|
Button,
|
|
5020
5444
|
{
|
|
5021
5445
|
type: "button",
|
|
@@ -5025,12 +5449,12 @@ function PublishDrawer({
|
|
|
5025
5449
|
disabled: busy,
|
|
5026
5450
|
className: "w-fit",
|
|
5027
5451
|
children: [
|
|
5028
|
-
status === "rendering-thumb" ? /* @__PURE__ */
|
|
5452
|
+
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
5453
|
"Gerar via Thumbify"
|
|
5030
5454
|
]
|
|
5031
5455
|
}
|
|
5032
5456
|
),
|
|
5033
|
-
thumbnailUrl && /* @__PURE__ */
|
|
5457
|
+
thumbnailUrl && /* @__PURE__ */ jsx64(
|
|
5034
5458
|
"img",
|
|
5035
5459
|
{
|
|
5036
5460
|
src: thumbnailUrl,
|
|
@@ -5039,26 +5463,26 @@ function PublishDrawer({
|
|
|
5039
5463
|
}
|
|
5040
5464
|
)
|
|
5041
5465
|
] }),
|
|
5042
|
-
/* @__PURE__ */
|
|
5043
|
-
/* @__PURE__ */
|
|
5044
|
-
/* @__PURE__ */
|
|
5045
|
-
/* @__PURE__ */
|
|
5466
|
+
/* @__PURE__ */ jsxs32("div", { className: "grid gap-2", children: [
|
|
5467
|
+
/* @__PURE__ */ jsx64(Label3, { htmlFor: "pd-account", children: "Canal do YouTube" }),
|
|
5468
|
+
/* @__PURE__ */ jsxs32(Select, { value: accountId ?? void 0, onValueChange: setAccountId, disabled: busy || accounts.length === 0, children: [
|
|
5469
|
+
/* @__PURE__ */ jsx64(SelectTrigger, { id: "pd-account", children: /* @__PURE__ */ jsx64(
|
|
5046
5470
|
SelectValue,
|
|
5047
5471
|
{
|
|
5048
5472
|
placeholder: status === "loading-accounts" ? "Carregando canais\u2026" : accounts.length === 0 ? "Nenhum canal conectado" : "Selecione um canal"
|
|
5049
5473
|
}
|
|
5050
5474
|
) }),
|
|
5051
|
-
/* @__PURE__ */
|
|
5475
|
+
/* @__PURE__ */ jsx64(SelectContent, { children: accounts.map((a) => /* @__PURE__ */ jsx64(SelectItem, { value: a.account_id, children: a.account_name ?? a.account_id }, a.id)) })
|
|
5052
5476
|
] })
|
|
5053
5477
|
] }),
|
|
5054
|
-
errorMsg && /* @__PURE__ */
|
|
5055
|
-
/* @__PURE__ */
|
|
5478
|
+
errorMsg && /* @__PURE__ */ jsxs32("p", { className: "flex items-center gap-2 text-sm text-destructive", children: [
|
|
5479
|
+
/* @__PURE__ */ jsx64(AlertCircle, { className: "h-4 w-4" }),
|
|
5056
5480
|
errorMsg
|
|
5057
5481
|
] }),
|
|
5058
|
-
/* @__PURE__ */
|
|
5059
|
-
/* @__PURE__ */
|
|
5060
|
-
/* @__PURE__ */
|
|
5061
|
-
status === "publishing" && /* @__PURE__ */
|
|
5482
|
+
/* @__PURE__ */ jsxs32(SheetFooter, { className: "mt-auto", children: [
|
|
5483
|
+
/* @__PURE__ */ jsx64(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: busy, children: "Cancelar" }),
|
|
5484
|
+
/* @__PURE__ */ jsxs32(Button, { onClick: handlePublish, disabled: busy, children: [
|
|
5485
|
+
status === "publishing" && /* @__PURE__ */ jsx64(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
5062
5486
|
"Publicar"
|
|
5063
5487
|
] })
|
|
5064
5488
|
] })
|
|
@@ -5074,9 +5498,9 @@ function useIframeAuth() {
|
|
|
5074
5498
|
}
|
|
5075
5499
|
|
|
5076
5500
|
// src/hooks/use-iframe-navigate.ts
|
|
5077
|
-
import { useCallback as
|
|
5501
|
+
import { useCallback as useCallback8 } from "react";
|
|
5078
5502
|
function useIframeNavigate() {
|
|
5079
|
-
return
|
|
5503
|
+
return useCallback8((path) => {
|
|
5080
5504
|
if (!window.parent || window.parent === window) return;
|
|
5081
5505
|
window.parent.postMessage(
|
|
5082
5506
|
{ type: "DFL_NAVIGATE", path },
|
|
@@ -5091,7 +5515,7 @@ import {
|
|
|
5091
5515
|
useContext as useContext9,
|
|
5092
5516
|
useMemo as useMemo5
|
|
5093
5517
|
} from "react";
|
|
5094
|
-
import { jsx as
|
|
5518
|
+
import { jsx as jsx65 } from "react/jsx-runtime";
|
|
5095
5519
|
var FeatureFlagContext = createContext8({
|
|
5096
5520
|
flags: {},
|
|
5097
5521
|
isEnabled: () => false
|
|
@@ -5107,7 +5531,7 @@ var FeatureFlagProvider = ({
|
|
|
5107
5531
|
}),
|
|
5108
5532
|
[flags]
|
|
5109
5533
|
);
|
|
5110
|
-
return /* @__PURE__ */
|
|
5534
|
+
return /* @__PURE__ */ jsx65(FeatureFlagContext.Provider, { value, children });
|
|
5111
5535
|
};
|
|
5112
5536
|
var useFeatureFlag = (flag) => {
|
|
5113
5537
|
const { isEnabled } = useContext9(FeatureFlagContext);
|
|
@@ -5200,6 +5624,7 @@ export {
|
|
|
5200
5624
|
ContextMenuSubContent,
|
|
5201
5625
|
ContextMenuSubTrigger,
|
|
5202
5626
|
ContextMenuTrigger,
|
|
5627
|
+
DEFAULT_NAME_COL_WIDTH,
|
|
5203
5628
|
DflRemote,
|
|
5204
5629
|
Dialog,
|
|
5205
5630
|
DialogClose,
|
|
@@ -5244,6 +5669,7 @@ export {
|
|
|
5244
5669
|
FormItem,
|
|
5245
5670
|
FormLabel,
|
|
5246
5671
|
FormMessage,
|
|
5672
|
+
Gantt,
|
|
5247
5673
|
HoverCard,
|
|
5248
5674
|
HoverCardContent,
|
|
5249
5675
|
HoverCardTrigger,
|
|
@@ -5384,7 +5810,9 @@ export {
|
|
|
5384
5810
|
UserAvatar,
|
|
5385
5811
|
UserMenu,
|
|
5386
5812
|
badgeVariants,
|
|
5813
|
+
barGridColumn,
|
|
5387
5814
|
buttonVariants,
|
|
5815
|
+
clampPct,
|
|
5388
5816
|
cn,
|
|
5389
5817
|
filterPublishableAccounts,
|
|
5390
5818
|
getInitials,
|
|
@@ -5396,6 +5824,10 @@ export {
|
|
|
5396
5824
|
memberHueVar,
|
|
5397
5825
|
navigationMenuTriggerStyle,
|
|
5398
5826
|
parseTags,
|
|
5827
|
+
resolveNameColWidth,
|
|
5828
|
+
resolveWeekCount,
|
|
5829
|
+
resolveWeekLabels,
|
|
5830
|
+
stageProgress,
|
|
5399
5831
|
toast,
|
|
5400
5832
|
toggleVariants,
|
|
5401
5833
|
useAuth,
|