@drawnagency/primitives 0.1.21 → 0.1.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorShell.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAYjD,OAAO,sBAAsB,CAAC;AAkC9B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAcxD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC;CACjE;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,MAAM,EACN,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,WAAW,GACZ,EAAE,KAAK,2CAskBP"}
1
+ {"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorShell.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAYjD,OAAO,sBAAsB,CAAC;AAkC9B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAcxD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC;CACjE;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,MAAM,EACN,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,WAAW,GACZ,EAAE,KAAK,2CAukBP"}
@@ -2,6 +2,7 @@ type BuildState = "idle" | "building" | "ready" | "error";
2
2
  interface BuildStatusResult {
3
3
  state: BuildState;
4
4
  deployUrl: string | null;
5
+ elapsedSeconds: number;
5
6
  startTracking: () => void;
6
7
  dismiss: () => void;
7
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useBuildStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useBuildStatus.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAS1D,UAAU,iBAAiB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAKD,wBAAgB,cAAc,IAAI,iBAAiB,CAsGlD"}
1
+ {"version":3,"file":"useBuildStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useBuildStatus.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAS1D,UAAU,iBAAiB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAKD,wBAAgB,cAAc,IAAI,iBAAiB,CAsHlD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawnagency/primitives",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
@@ -585,6 +585,7 @@ export default function EditorShell({
585
585
  }}
586
586
  processingItems={mediaPipeline.processingItems}
587
587
  buildState={buildStatus.state}
588
+ buildElapsed={buildStatus.elapsedSeconds}
588
589
  onBuildDismiss={buildStatus.dismiss}
589
590
  />
590
591
 
@@ -878,43 +879,63 @@ function LoadingEllipsis() {
878
879
  const id = setInterval(() => setDots((d) => (d + 1) % 4), 400);
879
880
  return () => clearInterval(id);
880
881
  }, []);
881
- return <>{".".repeat(dots)}</>;
882
+ return <span className="absolute">{".".repeat(dots)}</span>;
883
+ }
884
+
885
+ function formatElapsed(seconds: number): string {
886
+ const m = Math.floor(seconds / 60);
887
+ const s = seconds % 60;
888
+ return `${m}:${s.toString().padStart(2, "0")}`;
889
+ }
890
+
891
+ function DismissButton({ onClick }: { onClick: () => void }) {
892
+ return (
893
+ <button type="button" onClick={onClick} className="cursor-pointer" aria-label="Dismiss">
894
+ <X size={12} className="text-base-content/30 hover:text-base-content/60" />
895
+ </button>
896
+ );
882
897
  }
883
898
 
884
899
  function StatusText({
885
900
  publishAction,
886
901
  publishFeedback,
887
902
  buildState,
903
+ buildElapsed,
888
904
  onDismiss,
889
905
  }: {
890
906
  publishAction: "idle" | "saving" | "publishing";
891
907
  publishFeedback: string | null;
892
908
  buildState: "idle" | "building" | "ready" | "error";
909
+ buildElapsed: number;
893
910
  onDismiss: () => void;
894
911
  }) {
895
912
  if (publishAction === "saving") {
896
- return <span className="text-xs font-medium text-base-content/60">Saving changes<LoadingEllipsis /></span>;
913
+ return (
914
+ <span className="relative text-xs font-medium text-base-content/60">
915
+ Saving changes<LoadingEllipsis />
916
+ </span>
917
+ );
897
918
  }
898
919
  if (publishAction === "publishing" || buildState === "building") {
899
- return <span className="text-xs font-medium text-base-content/60">Publishing<LoadingEllipsis /></span>;
920
+ return (
921
+ <span className="text-xs font-medium text-orange-600">
922
+ Publishing ({formatElapsed(buildElapsed)})
923
+ </span>
924
+ );
900
925
  }
901
926
  if (buildState === "ready") {
902
927
  return (
903
- <span className="inline-flex items-center gap-1 text-xs font-medium text-green-600">
904
- <button type="button" onClick={onDismiss} className="text-base-content/30 hover:text-base-content/60 cursor-pointer" aria-label="Dismiss">
905
- <X size={12} />
906
- </button>
907
- Published
928
+ <span className="inline-flex items-center gap-1.5 text-xs font-medium text-green-600">
929
+ Published in {formatElapsed(buildElapsed)}
930
+ <DismissButton onClick={onDismiss} />
908
931
  </span>
909
932
  );
910
933
  }
911
934
  if (buildState === "error") {
912
935
  return (
913
- <span className="inline-flex items-center gap-1 text-xs font-medium text-red-600">
914
- <button type="button" onClick={onDismiss} className="text-base-content/30 hover:text-base-content/60 cursor-pointer" aria-label="Dismiss">
915
- <X size={12} />
916
- </button>
936
+ <span className="inline-flex items-center gap-1.5 text-xs font-medium text-red-600">
917
937
  Publish failed
938
+ <DismissButton onClick={onDismiss} />
918
939
  </span>
919
940
  );
920
941
  }
@@ -944,6 +965,7 @@ function EditorToolbar({
944
965
  onMediaClick,
945
966
  processingItems,
946
967
  buildState,
968
+ buildElapsed,
947
969
  onBuildDismiss,
948
970
  }: {
949
971
  buttonState: "synced" | "publish" | "saveAndPublish";
@@ -958,6 +980,7 @@ function EditorToolbar({
958
980
  onMediaClick: () => void;
959
981
  processingItems: QueueItem[];
960
982
  buildState: "idle" | "building" | "ready" | "error";
983
+ buildElapsed: number;
961
984
  onBuildDismiss: () => void;
962
985
  }) {
963
986
  const { isEditMode, viewBranch, setViewBranch, toggleEditMode } = useEditorContext();
@@ -1006,6 +1029,7 @@ function EditorToolbar({
1006
1029
  publishAction={publishAction}
1007
1030
  publishFeedback={publishFeedback}
1008
1031
  buildState={buildState}
1032
+ buildElapsed={buildElapsed}
1009
1033
  onDismiss={onBuildDismiss}
1010
1034
  />
1011
1035
  </div>
@@ -12,6 +12,7 @@ interface BuildStatusResponse {
12
12
  interface BuildStatusResult {
13
13
  state: BuildState;
14
14
  deployUrl: string | null;
15
+ elapsedSeconds: number;
15
16
  startTracking: () => void;
16
17
  dismiss: () => void;
17
18
  }
@@ -22,10 +23,22 @@ const AUTO_CLEAR_DELAY = 5000;
22
23
  export function useBuildStatus(): BuildStatusResult {
23
24
  const [state, setState] = useState<BuildState>("idle");
24
25
  const [deployUrl, setDeployUrl] = useState<string | null>(null);
26
+ const [elapsedSeconds, setElapsedSeconds] = useState(0);
25
27
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
26
28
  const clearRef = useRef<ReturnType<typeof setTimeout> | null>(null);
29
+ const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
27
30
  const isPolling = useRef(false);
28
31
 
32
+ const stopTimer = useCallback(() => {
33
+ if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; }
34
+ }, []);
35
+
36
+ const startTimer = useCallback(() => {
37
+ stopTimer();
38
+ setElapsedSeconds(0);
39
+ timerRef.current = setInterval(() => setElapsedSeconds((s) => s + 1), 1000);
40
+ }, [stopTimer]);
41
+
29
42
  const stopPolling = useCallback(() => {
30
43
  if (pollRef.current) {
31
44
  clearInterval(pollRef.current);
@@ -66,6 +79,7 @@ export function useBuildStatus(): BuildStatusResult {
66
79
 
67
80
  if (data.state === "ready" || data.state === "error") {
68
81
  stopPolling();
82
+ stopTimer();
69
83
  if (data.state === "ready") {
70
84
  clearRef.current = setTimeout(() => setState("idle"), AUTO_CLEAR_DELAY);
71
85
  }
@@ -103,6 +117,7 @@ export function useBuildStatus(): BuildStatusResult {
103
117
  return () => {
104
118
  cancelled = true;
105
119
  stopPolling();
120
+ stopTimer();
106
121
  if (clearRef.current) clearTimeout(clearRef.current);
107
122
  };
108
123
  }, [fetchStatus, handleStatusUpdate, startPolling, stopPolling]);
@@ -111,14 +126,16 @@ export function useBuildStatus(): BuildStatusResult {
111
126
  if (clearRef.current) { clearTimeout(clearRef.current); clearRef.current = null; }
112
127
  setState("building");
113
128
  setDeployUrl(null);
129
+ startTimer();
114
130
  startPolling();
115
- }, [startPolling]);
131
+ }, [startPolling, startTimer]);
116
132
 
117
133
  const dismiss = useCallback(() => {
118
134
  if (clearRef.current) { clearTimeout(clearRef.current); clearRef.current = null; }
119
135
  setState("idle");
120
136
  stopPolling();
121
- }, [stopPolling]);
137
+ stopTimer();
138
+ }, [stopPolling, stopTimer]);
122
139
 
123
- return { state, deployUrl, startTracking, dismiss };
140
+ return { state, deployUrl, elapsedSeconds, startTracking, dismiss };
124
141
  }