@open-flow/ui 0.3.0 → 0.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/app.d.ts +2 -1
- package/dist/app.js +1 -1
- package/dist/connect-popover.d.ts +24 -0
- package/dist/connect-popover.js +1 -0
- package/dist/dev-actions.d.ts +2 -1
- package/dist/dev-actions.js +1 -1
- package/dist/dev-actions.noop.d.ts +2 -1
- package/dist/dev-actions.noop.js +1 -1
- package/dist/flow-edit.d.ts +30 -0
- package/dist/flow-edit.js +1 -0
- package/dist/flow-frames.d.ts +23 -0
- package/dist/flow-frames.js +1 -0
- package/dist/flow-layout.d.ts +35 -0
- package/dist/flow-layout.js +1 -0
- package/dist/flow-start.d.ts +9 -0
- package/dist/flow-start.js +1 -0
- package/dist/frame-view.js +1 -1
- package/dist/frame.d.ts +16 -1
- package/dist/frame.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/manifest.d.ts +3 -2
- package/dist/manifest.js +1 -1
- package/dist/manifest.types.d.ts +9 -1
- package/dist/manifest.types.js +1 -1
- package/dist/panels/components.js +1 -1
- package/dist/panels/elements.js +1 -1
- package/dist/panels/flow-cards.d.ts +50 -0
- package/dist/panels/flow-cards.js +1 -0
- package/dist/panels/flows.d.ts +5 -3
- package/dist/panels/flows.js +1 -1
- package/dist/pick-highlight.d.ts +21 -0
- package/dist/pick-highlight.js +1 -1
- package/dist/pin.d.ts +34 -0
- package/dist/screen-frame.d.ts +10 -1
- package/dist/screen-frame.js +1 -1
- package/dist/screen-toolbar.js +1 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.js +2 -1
- package/dist/workbench-app.d.ts +3 -2
- package/dist/workbench-app.js +1 -1
- package/package.json +1 -1
package/dist/app.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
1
|
+
import type { NewTicketInput, SaveFlowInput, SaveFlowResult, TicketSummary } from "./pin";
|
|
2
2
|
import type { RegistryEntry } from "./registry";
|
|
3
3
|
import type { CreateResult } from "./ticket-drawer";
|
|
4
4
|
export interface WorkbenchClientProps {
|
|
@@ -6,5 +6,6 @@ export interface WorkbenchClientProps {
|
|
|
6
6
|
registry: RegistryEntry[];
|
|
7
7
|
onCreateTicket: (input: NewTicketInput) => Promise<CreateResult>;
|
|
8
8
|
onLoadTickets?: () => Promise<TicketSummary[]>;
|
|
9
|
+
onSaveFlow?: (input: SaveFlowInput) => Promise<SaveFlowResult>;
|
|
9
10
|
}
|
|
10
11
|
export declare function WorkbenchClient(props: WorkbenchClientProps): import("react").JSX.Element;
|
package/dist/app.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as r}from"react/jsx-runtime";import{Suspense as
|
|
1
|
+
"use client";import{jsx as r}from"react/jsx-runtime";import{Suspense as d,useEffect as l,useMemo as h,useState as v}from"react";import{useSearchParams as g}from"next/navigation";import{FrameView as w}from"./frame-view";import{parseManifest as b}from"./parse-manifest";import{WorkbenchApp as k}from"./workbench-app";function V(n){return r(d,{fallback:null,children:r(x,{...n})})}function S(n){const e=o=>n.get(o)??void 0;return{tab:e("tab"),component:e("component"),flow:e("flow"),surface:e("surface"),vp:e("vp"),zoom:e("zoom"),theme:e("theme"),chrome:e("chrome")}}function x({manifest:n,registry:e,onCreateTicket:o,onLoadTickets:i,onSaveFlow:u}){const t=g(),[c,a]=v([]),m=h(()=>b(n),[n]);l(()=>{if(!i)return;let s=!0;return i().then(p=>{s&&a(p)}),()=>{s=!1}},[i]);const f=t.get("route")??void 0;return t.get("view")==="frame"||f?r(w,{manifest:m,registry:e,componentId:t.get("component")??void 0,route:f,viewport:t.get("viewport")??void 0,theme:t.get("theme")??void 0,scenario:t.get("scenario")??void 0}):r(k,{manifest:m,registry:e,tickets:c,view:S(t),onCreateTicket:o,onSaveFlow:u})}export{V as WorkbenchClient};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { MirrorPick } from "./frame";
|
|
2
|
+
export type PopoverMode = "append" | "fork" | "blocked";
|
|
3
|
+
export declare function placePopover(anchor: {
|
|
4
|
+
top: number;
|
|
5
|
+
left: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}, size: {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
}, viewport: {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
}): {
|
|
15
|
+
top: number;
|
|
16
|
+
left: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function ConnectPopover({ pick, route, mode, onConfirm, onCancel, }: {
|
|
19
|
+
pick: MirrorPick;
|
|
20
|
+
route: string | null;
|
|
21
|
+
mode: PopoverMode;
|
|
22
|
+
onConfirm: () => void;
|
|
23
|
+
onCancel: () => void;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsxs as l,jsx as u}from"react/jsx-runtime";import{useEffect as f,useLayoutEffect as b,useRef as c,useState as v}from"react";import{cx as z}from"./cx";import{CHIP as E}from"./screen-toolbar";function k(e,t,n){let r=e.top+e.height+6;r+t.height>n.height-8&&(r=Math.max(8,e.top-t.height-6));const o=Math.min(Math.max(e.left,8),Math.max(8,n.width-t.width-8));return{top:r,left:o}}function y(e,t){return e==="blocked"?"Una rama s\xF3lo sale del tronco; a\xF1ade al final de esta fila con \xAB+ A\xF1adir pantalla\xBB.":e==="fork"?"Este paso ya tiene una pantalla siguiente; la nueva empieza una rama.":t?"La nueva pantalla sigue a esta.":"El control no lleva a una ruta de esta app; escribe la ruta en la tarjeta."}function M({pick:e,route:t,mode:n,onConfirm:m,onCancel:r}){const o=c(null),p=c(null),h=c(null),[s,w]=v(null),d=c(r);return f(()=>{d.current=r},[r]),b(()=>{const a=o.current;a&&w(k(e.rect,{width:a.offsetWidth,height:a.offsetHeight},{width:window.innerWidth,height:window.innerHeight}))},[e,n]),f(()=>{s&&(n==="blocked"?h.current:p.current)?.focus()},[s,n]),f(()=>{const a=g=>{const x=g.target;(!(x instanceof Node)||!o.current?.contains(x))&&d.current()},i=()=>d.current();return document.addEventListener("pointerdown",a,!0),window.addEventListener("blur",i),window.addEventListener("scroll",i,!0),window.addEventListener("resize",i),()=>{document.removeEventListener("pointerdown",a,!0),window.removeEventListener("blur",i),window.removeEventListener("scroll",i,!0),window.removeEventListener("resize",i)}},[]),l("div",{ref:o,role:"dialog","aria-label":`Conectar \xAB${e.text||"control"}\xBB`,onKeyDown:a=>{a.key==="Escape"&&r()},className:"fixed z-[2147483050] w-64 rounded-md border border-zinc-200 bg-white p-2 shadow-lg dark:border-zinc-700 dark:bg-zinc-900",style:s?{top:s.top,left:s.left}:{top:0,left:0,visibility:"hidden"},children:[l("p",{className:"truncate text-[12px] font-medium text-zinc-900 dark:text-zinc-100",children:["\xAB",e.text||"sin texto","\xBB",t&&l("span",{className:"ml-1 font-mono text-[11px] font-normal text-zinc-500 dark:text-zinc-400",children:["\u2192 ",t]})]}),u("p",{className:"mt-0.5 text-[11px] text-zinc-500 dark:text-zinc-400",children:y(n,t)}),l("div",{className:"mt-2 flex items-center gap-2",children:[n!=="blocked"&&u("button",{ref:p,type:"button",onClick:m,className:"rounded-md bg-zinc-900 px-2.5 py-1 text-[11px] font-medium text-white dark:bg-zinc-100 dark:text-zinc-900",children:n==="fork"?"+ A\xF1adir rama desde aqu\xED":"+ A\xF1adir pantalla"}),u("button",{ref:h,type:"button",onClick:r,className:z(E),children:"Cancelar"})]})]})}export{M as ConnectPopover,k as placePopover};
|
package/dist/dev-actions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
1
|
+
import type { NewTicketInput, SaveFlowInput, TicketSummary } from "./pin";
|
|
2
2
|
export declare function createTicket(input: NewTicketInput): Promise<{
|
|
3
3
|
ok: boolean;
|
|
4
4
|
id?: string;
|
|
@@ -7,3 +7,4 @@ export declare function createTicket(input: NewTicketInput): Promise<{
|
|
|
7
7
|
error?: string;
|
|
8
8
|
}>;
|
|
9
9
|
export declare function loadTickets(): Promise<TicketSummary[]>;
|
|
10
|
+
export declare function saveFlow(input: SaveFlowInput): Promise<import("./pin").SaveFlowResult>;
|
package/dist/dev-actions.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use server";import{readTickets as r,writeTicket as
|
|
1
|
+
"use server";import{readTickets as r,saveFlow as t,writeTicket as n}from"./server";async function c(e){return n(e)}async function i(){return r()}async function s(e){return t(e)}export{c as createTicket,i as loadTickets,s as saveFlow};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
1
|
+
import type { NewTicketInput, SaveFlowInput, TicketSummary } from "./pin";
|
|
2
2
|
export declare function createTicket(_input: NewTicketInput): Promise<never>;
|
|
3
3
|
export declare function loadTickets(): Promise<TicketSummary[]>;
|
|
4
|
+
export declare function saveFlow(_input: SaveFlowInput): Promise<never>;
|
package/dist/dev-actions.noop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const r="El taller s\xF3lo escribe en desarrollo.";async function n(e){throw new Error(r)}async function o(){return[]}async function t(e){throw new Error(r)}export{n as createTicket,o as loadTickets,t as saveFlow};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Flow } from "./manifest.types";
|
|
2
|
+
import type { FlowBody, FlowStepInput } from "./pin";
|
|
3
|
+
export type LaneRef = {
|
|
4
|
+
kind: "trunk";
|
|
5
|
+
} | {
|
|
6
|
+
kind: "branch";
|
|
7
|
+
index: number;
|
|
8
|
+
id: string;
|
|
9
|
+
};
|
|
10
|
+
export interface ComposerTarget {
|
|
11
|
+
lane: LaneRef;
|
|
12
|
+
after: number;
|
|
13
|
+
anchorRoute: string;
|
|
14
|
+
fork: boolean;
|
|
15
|
+
flat: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function bodyOf(flow: Flow, defaultViewport?: string): FlowBody;
|
|
18
|
+
export declare function appendStep(body: FlowBody, lane: LaneRef, step: FlowStepInput): FlowBody;
|
|
19
|
+
export declare function forkFrom(body: FlowBody, fromRoute: string, branchLabel: string, step: FlowStepInput): FlowBody;
|
|
20
|
+
export declare function removeLast(body: FlowBody, lane: LaneRef): FlowBody;
|
|
21
|
+
export declare function isForkPoint(flow: Flow, position: number): boolean;
|
|
22
|
+
export declare function forkResolvesTo(flow: Flow, route: string): number;
|
|
23
|
+
export declare function routeOfHref(href: string | null, origin: string): string | null;
|
|
24
|
+
export declare function hasStepAt(flow: Flow, at: ComposerTarget, route: string): boolean;
|
|
25
|
+
export declare function stepInputOf(draft: {
|
|
26
|
+
route: string;
|
|
27
|
+
label: string;
|
|
28
|
+
spec: string;
|
|
29
|
+
via: string;
|
|
30
|
+
}, viewport: string): FlowStepInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const i=e=>e??"";function p(e,t){return{route:e.route,label:e.label,via:i(e.via),viewport:e.viewport===t?"":e.viewport,note:i(e.note),spec:i(e.spec)}}function c(e,t=""){const r=n=>p(n,t);return{title:e.title,description:i(e.description),intent:"",acceptance:"",steps:e.steps.map(r),branches:e.branches.map(n=>({id:n.id,label:n.label,from:e.steps[n.from]?.route??"",steps:n.steps.map(r)}))}}function f(e,t,r){return t.kind==="trunk"?{...e,steps:[...e.steps,r]}:{...e,branches:e.branches.map((n,s)=>s===t.index?{...n,steps:[...n.steps,r]}:n)}}function a(e,t,r,n){return{...e,branches:[...e.branches,{label:r,from:t,steps:[n]}]}}function l(e,t){if(t.kind==="trunk")return{...e,steps:e.steps.slice(0,-1)};const r=e.branches.map((n,s)=>s===t.index?{...n,steps:n.steps.slice(0,-1)}:n);return{...e,branches:r.filter(n=>n.steps.length>0)}}function m(e,t){return e.branches.some(r=>r.from===t)}function u(e,t){return e.steps.findIndex(r=>r.route===t)}function x(e,t){if(!e)return null;try{const r=new URL(e,t);return r.origin===t?r.pathname:null}catch{return null}}function k(e,t,r){if(t.fork){const n=u(e,e.steps[t.after]?.route??"");return e.branches.some(s=>s.from===n&&s.steps[0]?.route===r)}return t.lane.kind==="trunk"?e.steps[t.after+1]?.route===r:e.branches[t.lane.index]?.steps[t.after+1]?.route===r}function v(e,t){const r={route:e.route.trim()};t&&(r.viewport=t);const n=e.label.trim();n&&(r.label=n);const s=e.via.trim();s&&(r.via=s);const o=e.spec.trim();return o&&(r.spec=o),r}export{f as appendStep,c as bodyOf,a as forkFrom,u as forkResolvesTo,k as hasStepAt,m as isForkPoint,l as removeLast,x as routeOfHref,v as stepInputOf};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { StepNode } from "./flow-layout";
|
|
2
|
+
export type StepFrame = {
|
|
3
|
+
kind: "queued";
|
|
4
|
+
} | {
|
|
5
|
+
kind: "capturing";
|
|
6
|
+
ticket: number;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "mirrored";
|
|
9
|
+
srcdoc: string;
|
|
10
|
+
capturedAt: number;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "restless";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "unbuilt";
|
|
15
|
+
};
|
|
16
|
+
export declare const QUEUED: StepFrame;
|
|
17
|
+
export declare const UNBUILT: StepFrame;
|
|
18
|
+
export type Frames = ReadonlyMap<string, StepFrame>;
|
|
19
|
+
export declare const NO_FRAMES: Frames;
|
|
20
|
+
export declare function frameOf(frames: Frames, node: StepNode): StepFrame;
|
|
21
|
+
export declare function nextCapture(frames: Frames, nodes: readonly StepNode[]): string | null;
|
|
22
|
+
export declare function withFrame(frames: Frames, key: string, frame: StepFrame): Frames;
|
|
23
|
+
export declare function prune(frames: Frames, nodes: readonly StepNode[]): Frames;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const p={kind:"queued"},f={kind:"unbuilt"},s=new Map;function u(e,t){return t.step.exists?e.get(t.key)??p:f}function c(e,t){for(const n of t)if(u(e,n).kind==="capturing")return null;for(const n of t)if(u(e,n).kind==="queued")return n.key;return null}function x(e,t,n){const o=new Map(e);return o.set(t,n),o}function k(e,t){const n=new Set(t.filter(r=>r.step.exists).map(r=>r.key));if([...e.keys()].every(r=>n.has(r)))return e;const o=new Map;for(const[r,i]of e)n.has(r)&&o.set(r,i);return o}export{s as NO_FRAMES,p as QUEUED,f as UNBUILT,u as frameOf,c as nextCapture,k as prune,x as withFrame};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Flow, FlowStep, Viewport } from "./manifest.types";
|
|
2
|
+
import { type RowExtent } from "./screen-frame";
|
|
3
|
+
export interface StepNode {
|
|
4
|
+
key: string;
|
|
5
|
+
flat: number;
|
|
6
|
+
number: number;
|
|
7
|
+
step: FlowStep;
|
|
8
|
+
viewport: Viewport;
|
|
9
|
+
}
|
|
10
|
+
export declare function laneKey(branchId: string | null): string;
|
|
11
|
+
export type Lane = {
|
|
12
|
+
kind: "trunk";
|
|
13
|
+
nodes: StepNode[];
|
|
14
|
+
} | {
|
|
15
|
+
kind: "branch";
|
|
16
|
+
id: string;
|
|
17
|
+
index: number;
|
|
18
|
+
label: string;
|
|
19
|
+
from: number;
|
|
20
|
+
fork: number | null;
|
|
21
|
+
nodes: StepNode[];
|
|
22
|
+
};
|
|
23
|
+
export declare function layOut(flow: Flow, viewportOf: (id: string) => Viewport): {
|
|
24
|
+
lanes: Lane[];
|
|
25
|
+
nodes: StepNode[];
|
|
26
|
+
};
|
|
27
|
+
export declare function forkPrefix(lanes: readonly Lane[], fork: number | null): number[];
|
|
28
|
+
export interface RowTails {
|
|
29
|
+
tail: ReadonlyMap<string, number>;
|
|
30
|
+
forkRow: {
|
|
31
|
+
fork: number;
|
|
32
|
+
width: number;
|
|
33
|
+
} | null;
|
|
34
|
+
}
|
|
35
|
+
export declare function rowExtents(lanes: readonly Lane[], tails?: RowTails): RowExtent[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{rowExtent as d}from"./screen-frame";function c(r){return r===null?"trunk":`branch:${r}`}function w(r,t){const e=[],n=(s,o,f)=>s.map((k,p)=>({key:`${f}:${p}:${k.route}`,flat:e.length+p,number:o+p,step:k,viewport:t(k.viewport)})),u=n(r.steps,1,c(null));e.push(...u);const i=[{kind:"trunk",nodes:u}];for(const[s,o]of r.branches.entries()){const f=n(o.steps,o.from+2,c(o.id));e.push(...f),i.push({kind:"branch",id:o.id,index:s,label:o.label,from:o.from,fork:u[o.from]?.flat??null,nodes:f})}return{lanes:i,nodes:e}}function l(r,t){return t===null?[]:(r.find(n=>n.kind==="trunk")?.nodes??[]).slice(0,t+1).map(n=>n.viewport.width)}function m(r,t){const e=r.map(n=>{const u=n.kind==="trunk"?c(null):c(n.id),i=t?.tail.get(u)??0;return d([...n.kind==="branch"?l(r,n.fork):[],...n.nodes.map(s=>s.viewport.width),...i>0?[i]:[]])});return t?.forkRow&&e.push(d([...l(r,t.forkRow.fork),t.forkRow.width])),e}export{l as forkPrefix,c as laneKey,w as layOut,m as rowExtents};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SaveFlowInput, SaveFlowResult } from "./pin";
|
|
2
|
+
export declare function FlowStart({ routes, waiting, onSave, onCreated, onCancel, onReset, }: {
|
|
3
|
+
routes: string[];
|
|
4
|
+
waiting: string | null;
|
|
5
|
+
onSave: (input: SaveFlowInput) => Promise<SaveFlowResult>;
|
|
6
|
+
onCreated: (flowId: string) => void;
|
|
7
|
+
onCancel?: () => void;
|
|
8
|
+
onReset: () => void;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as t,Fragment as x,jsxs as r}from"react/jsx-runtime";import{useState as a}from"react";const b="mt-1 w-full rounded-md border border-zinc-300 px-2 py-1.5 text-[13px] dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-100",h="text-[11px] font-medium uppercase tracking-wider text-zinc-400",f="workbench-flow-start-routes";function F({routes:k,waiting:o,onSave:z,onCreated:N,onCancel:l,onReset:y}){const[n,g]=a(""),[c,v]=a("/"),[i,s]=a(!1),[m,d]=a(null),[u,p]=a(null),w=async()=>{if(!(i||!n.trim()||!c.trim())){s(!0),d(null);try{const e=await z({id:null,title:n.trim(),description:"",intent:"",acceptance:"",steps:[{route:c.trim()}],branches:[]});e.ok&&e.flowId?(p(e.note??null),N(e.flowId)):(d(e.error??"Fall\xF3 la escritura."),s(!1))}catch(e){d(e instanceof Error?e.message:"Fall\xF3 la escritura."),s(!1)}}};return t("div",{className:"flex h-full items-center justify-center p-10",children:r("div",{className:"w-80",children:[t("h2",{className:"text-sm font-semibold text-zinc-900 dark:text-zinc-100",children:"A\xF1adir recorrido"}),o?r("div",{className:"mt-2 space-y-3",children:[t("p",{role:"status",className:"text-[12px] text-zinc-600 dark:text-zinc-300",children:u?r(x,{children:["Recorrido \xAB",o,"\xBB creado. ",u]}):r(x,{children:["Recorrido \xAB",o,"\xBB creado \u2014 cargando el mapa\u2026"]})}),u&&t("button",{type:"button",onClick:()=>{p(null),s(!1),y()},className:"rounded-md border border-zinc-300 px-3 py-1.5 text-[12px] text-zinc-700 dark:border-zinc-700 dark:text-zinc-200",children:"Volver"})]}):r("form",{className:"mt-3 space-y-3",onSubmit:e=>{e.preventDefault(),w()},onKeyDown:e=>{e.key==="Escape"&&l&&(e.stopPropagation(),l())},children:[t("p",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",children:"Un t\xEDtulo y su primera pantalla; el resto del recorrido se compone en el tablero, pantalla a pantalla."}),r("label",{className:"block",children:[t("span",{className:h,children:"T\xEDtulo"}),t("input",{value:n,onChange:e=>g(e.target.value),placeholder:"Checkout por m\xE9todo",autoFocus:!0,className:b})]}),r("label",{className:"block",children:[t("span",{className:h,children:"Primera pantalla"}),t("input",{value:c,onChange:e=>v(e.target.value),list:f,placeholder:"/",className:`${b} font-mono`}),t("datalist",{id:f,children:k.map(e=>t("option",{value:e},e))})]}),m&&t("p",{role:"alert",className:"text-[11px] text-red-700 dark:text-red-300",children:m}),r("div",{className:"flex items-center gap-2",children:[t("button",{type:"submit",disabled:i||!n.trim()||!c.trim(),className:"rounded-md bg-zinc-900 px-3 py-1.5 text-[12px] font-medium text-white disabled:opacity-40 dark:bg-zinc-100 dark:text-zinc-900",children:i?"Creando\u2026":"Crear"}),l&&t("button",{type:"button",onClick:l,className:"rounded-md border border-zinc-300 px-3 py-1.5 text-[12px] text-zinc-700 dark:border-zinc-700 dark:text-zinc-200",children:"Cancelar"})]})]})]})})}export{F as FlowStart};
|
package/dist/frame-view.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{useCallback as
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{useCallback as F,useMemo as I,useRef as H,useState as p}from"react";import{ComponentPreview as M,ScenarioPreview as V}from"./component-preview";import{ManifestProvider as B}from"./config-context";import{useInspect as O}from"./edit-mode";import{EditSessionOverlay as T,useEditSession as U}from"./edit-session";import{InlineSurface as b,RouteFrame as Z}from"./frame";import{buildComponentIndex as _}from"./hover-inspect";import{viewportById as q,workbenchUrl as A}from"./manifest";import{PickBox as K}from"./pick-box";import{indexRegistry as k}from"./registry";import{rowExtent as D,ScreenFrame as y,useScale as G}from"./screen-frame";import{AUTO as N,ScreenToolbar as J}from"./screen-toolbar";function le({manifest:r,registry:f,componentId:h,route:t,viewport:S,theme:c,scenario:s}){const g=r.config,[d,E]=p(S??N),[m,P]=p("fit"),[u,$]=p(c==="dark"||c==="split"?c:"light"),i=U({bareKeys:!0}),w=H(null),z=I(()=>_(r.components),[r.components]),n=r.components.find(C=>C.id===h),o=d===N?null:q(g,d),{ref:R,scale:v}=G(m,[D([o?.width??0])]),l=u==="dark"?"dark":"light";O(i.editing,F(()=>w.current,[]),z,{onPin:i.addPin,onHover:i.setHovering},`${h??t}:${d}:${m}:${l}`);const x=n?s?e(V,{entry:n,registry:k(f).get(n.id),scenario:s}):e(M,{entry:n,registry:k(f).get(n.id)}):a("p",{className:"p-6 text-sm text-zinc-500",children:["Nada que mostrar. Falta ",e("code",{children:"?component="})," o ",e("code",{children:"?route="}),"."]}),j=t?o?e(y,{viewport:o,scale:v,label:t,editing:i.editing,children:e(Z,{src:t,title:t,width:o.width,height:o.height})}):e(K,{enabled:i.editing,className:"h-full",children:e("iframe",{src:t,title:t,className:"h-full w-full border-0"})}):o?e(y,{viewport:o,scale:v,label:n?.name,editing:i.editing,children:e(b,{theme:l,editing:!1,children:x})}):e(b,{theme:l,editing:i.editing,children:x});return a(B,{manifest:r,children:[e("div",{className:l==="dark"?"dark":void 0,children:a("div",{className:"flex h-screen flex-col bg-white dark:bg-zinc-900",children:[e(J,{viewport:d,onViewport:E,zoom:m,onZoom:P,theme:u,onTheme:$,zoomEnabled:o!==null,identity:t??(s?`${n?.name} \xB7 ${s}`:n?.name),backHref:A(g,""),editing:i.editing,onToggleEdit:i.toggleEditing,pinCount:i.pins.length}),e("div",{ref:R,className:"min-h-0 flex-1 overflow-auto",children:e("div",{ref:w,className:"h-full p-4",children:j})})]})}),e(T,{session:i})]})}export{le as FrameView};
|
package/dist/frame.d.ts
CHANGED
|
@@ -20,10 +20,25 @@ export declare function RouteFrame({ src, title, width, height, theme, frameRef,
|
|
|
20
20
|
frameRef?: (frame: HTMLIFrameElement | null) => void;
|
|
21
21
|
onLoad?: (frame: HTMLIFrameElement) => void;
|
|
22
22
|
}): import("react").JSX.Element;
|
|
23
|
-
export
|
|
23
|
+
export interface MirrorPick {
|
|
24
|
+
text: string;
|
|
25
|
+
href: string | null;
|
|
26
|
+
rect: {
|
|
27
|
+
top: number;
|
|
28
|
+
left: number;
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export declare const ACTIONABLE = "a[href], button, [role=\"button\"], input[type=\"submit\"]";
|
|
34
|
+
export declare function MirrorFrame({ srcdoc, title, width, height, theme, connect, }: {
|
|
24
35
|
srcdoc: string;
|
|
25
36
|
title: string;
|
|
26
37
|
width: number;
|
|
27
38
|
height: number;
|
|
28
39
|
theme: "light" | "dark";
|
|
40
|
+
connect?: {
|
|
41
|
+
onPick: (pick: MirrorPick | null) => void;
|
|
42
|
+
onHover: (pick: MirrorPick | null) => void;
|
|
43
|
+
};
|
|
29
44
|
}): import("react").JSX.Element;
|
package/dist/frame.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as d,jsxs as z}from"react/jsx-runtime";import{useEffect as g,useRef as k}from"react";import{cx as h}from"./cx";import{isElement as N,readProp as w}from"./dom-realm";import{PickBox as y}from"./pick-box";import{mapRect as j}from"./pick-highlight";function F({label:n,meta:o,children:c,className:s}){return z("div",{className:h("overflow-hidden rounded-lg border border-zinc-300 bg-white shadow-sm","dark:border-zinc-700 dark:bg-zinc-900",s),children:[(n||o)&&z("div",{className:"flex items-center justify-between gap-3 border-b border-zinc-200 bg-zinc-50 px-3 py-1.5 text-[11px] font-medium tracking-wide text-zinc-600 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300",children:[d("span",{className:"truncate",children:n}),o&&d("span",{className:"truncate font-mono text-[10px] text-zinc-500 dark:text-zinc-400",children:o})]}),c]})}function R({theme:n,children:o,padded:c=!0,editing:s}){return d("div",{className:h(n==="dark"&&"dark"),children:d(y,{enabled:s,className:h("bg-background text-foreground",c&&"p-6"),children:o})})}function B({src:n,title:o,width:c,height:s,theme:u,frameRef:m,onLoad:f}){const a=k(null);return g(()=>{if(u===void 0)return;const t=a.current;if(!t)return;const i=()=>{try{t.contentDocument?.documentElement.classList.toggle("dark",u==="dark")}catch{}};i(),t.addEventListener("load",i);const v=[300,1200,2500].map(l=>setTimeout(i,l));return()=>{t.removeEventListener("load",i);for(const l of v)clearTimeout(l)}},[u,n]),d("iframe",{ref:t=>{a.current=t,m?.(t)},src:n,title:o,width:c,height:s,onLoad:t=>f?.(t.currentTarget),className:"border-0 bg-white",style:{width:c,height:s}})}const D='a[href], button, [role="button"], input[type="submit"]';function H({srcdoc:n,title:o,width:c,height:s,theme:u,connect:m}){const f=k(null),a=k(m);return g(()=>{a.current=m},[m]),g(()=>{const t=f.current;if(!t)return;const i=e=>N(e)?e.closest(D):null,v=e=>{const r=e.closest("a[href]");return{text:((e.tagName==="INPUT"?String(w(e,"value")??""):"")||e.textContent||e.getAttribute("aria-label")||"").trim().replace(/\s+/g," ").slice(0,80),href:r?String(w(r,"href")):null,rect:j(e,t)}},l=e=>{const r=e.target;N(r)&&r.closest("a[href]")&&e.preventDefault();const b=i(r);a.current?.onPick(b?v(b):null)};let p=null;const E=e=>{if(!a.current)return;const r=i(e.target);r!==p&&(p=r,a.current.onHover(r?v(r):null))},L=()=>{p=null,a.current?.onHover(null)},x=()=>{try{const e=t.contentDocument;if(!e)return;e.documentElement.classList.toggle("dark",u==="dark"),e.addEventListener("click",l,!0),e.addEventListener("mouseover",E,!0),e.addEventListener("mouseleave",L)}catch{}};return x(),t.addEventListener("load",x),()=>{t.removeEventListener("load",x);try{const e=t.contentDocument;e?.removeEventListener("click",l,!0),e?.removeEventListener("mouseover",E,!0),e?.removeEventListener("mouseleave",L)}catch{}}},[u,n]),d("iframe",{ref:f,srcDoc:n,title:o,sandbox:"allow-same-origin","data-workbench-mirror":"",tabIndex:-1,width:c,height:s,className:"border-0 bg-white",style:{width:c,height:s}})}export{D as ACTIONABLE,F as FrameShell,R as InlineSurface,H as MirrorFrame,B as RouteFrame};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { byGroup, flowById, frameUrl, groupLabel, surfaceForRoute, surfaceFromPins, viewportById, workbenchUrl, MANIFEST_VERSION, } from "./manifest";
|
|
2
|
-
export type { ComponentEntry, Flow, FlowStep, HardcodedColor, LearnedFile, Manifest, Origin, PropSample, PropSpec, Renderability, RouteEntry, RouteKind, SampleKind, SampleValue, ScanStats, Surface, SurfaceFiles, Token, TokenGroup, TokenKind, TokenUse, Viewport, ViewerConfig, Weight, } from "./manifest";
|
|
1
|
+
export { byGroup, flowById, tokenCount, frameUrl, groupLabel, surfaceForRoute, surfaceFromPins, viewportById, workbenchUrl, MANIFEST_VERSION, } from "./manifest";
|
|
2
|
+
export type { ComponentEntry, Flow, FlowStep, FlowBranch, HardcodedColor, LearnedFile, Manifest, Origin, PropSample, PropSpec, Renderability, RouteEntry, RouteKind, SampleKind, SampleValue, ScanStats, Surface, SurfaceFiles, Token, TokenGroup, TokenKind, TokenUse, Viewport, ViewerConfig, Weight, } from "./manifest";
|
|
3
3
|
export { parseManifest } from "./parse-manifest";
|
|
4
4
|
export type { RegistryEntry } from "./registry";
|
|
5
|
-
export type { NewTicketInput, Pin, RuntimeError, TicketSummary } from "./pin";
|
|
5
|
+
export type { FlowBody, FlowBranchInput, FlowStepInput, NewTicketInput, Pin, RuntimeError, SaveFlowInput, SaveFlowResult, TicketSummary, } from "./pin";
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{byGroup as e,flowById as f,frameUrl as a,groupLabel as p,surfaceForRoute as
|
|
1
|
+
import{byGroup as e,flowById as f,tokenCount as t,frameUrl as a,groupLabel as p,surfaceForRoute as u,surfaceFromPins as n,viewportById as s,workbenchUrl as l,MANIFEST_VERSION as m}from"./manifest";import{parseManifest as b}from"./parse-manifest";export{m as MANIFEST_VERSION,e as byGroup,f as flowById,a as frameUrl,p as groupLabel,b as parseManifest,u as surfaceForRoute,n as surfaceFromPins,t as tokenCount,s as viewportById,l as workbenchUrl};
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ComponentEntry, Flow, Viewport, ViewerConfig } from "./manifest.types";
|
|
2
|
-
export type { ComponentEntry, Flow, FlowStep, HardcodedColor, LearnedFile, Manifest, Origin, PropSample, PropSpec, Renderability, RouteEntry, RouteKind, SampleKind, SampleValue, ScanStats, Surface, SurfaceFiles, Token, TokenGroup, TokenKind, TokenUse, Viewport, ViewerConfig, Weight, } from "./manifest.types";
|
|
1
|
+
import type { ComponentEntry, Flow, TokenGroup, Viewport, ViewerConfig } from "./manifest.types";
|
|
2
|
+
export type { ComponentEntry, Flow, FlowStep, FlowBranch, HardcodedColor, LearnedFile, Manifest, Origin, PropSample, PropSpec, Renderability, RouteEntry, RouteKind, SampleKind, SampleValue, ScanStats, Surface, SurfaceFiles, Token, TokenGroup, TokenKind, TokenUse, Viewport, ViewerConfig, Weight, } from "./manifest.types";
|
|
3
3
|
export { MANIFEST_VERSION } from "./manifest.types";
|
|
4
4
|
export declare function groupLabel(config: ViewerConfig, group: string): string;
|
|
5
5
|
export declare function viewportById(config: ViewerConfig, id: string | undefined): Viewport;
|
|
@@ -16,4 +16,5 @@ export declare function surfaceForRoute(routes: ReadonlyArray<{
|
|
|
16
16
|
dynamic: boolean;
|
|
17
17
|
}>, pathname: string): string | null;
|
|
18
18
|
export declare function frameUrl(config: ViewerConfig, params: Record<string, string>): string;
|
|
19
|
+
export declare function tokenCount(groups: TokenGroup[]): number;
|
|
19
20
|
export declare function flowById(flows: Flow[], id: string | undefined): Flow | undefined;
|
package/dist/manifest.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MANIFEST_VERSION as
|
|
1
|
+
import{MANIFEST_VERSION as w}from"./manifest.types";function f(e,t){return e.groupLabels[t]??t}function s(e,t){const n=e.viewports.find(r=>r.id===t),o=e.viewports[0];if(n)return n;if(o)return o;throw new Error("El manifiesto no declara ning\xFAn viewport.")}function u(e,t,n){const o=e.mountPath.replace(/\/+$/,""),r=t?`${o}/${t}`:o;return n?`${r}?${n.toString()}`:r}function c(e){const t=new Map;for(const n of e){const o=t.get(n.group);o?o.push(n):t.set(n.group,[n])}return[...t.entries()]}function p(e,t){const n=new Map;for(const r of e){const i=r.node?.surface;i&&n.set(i,(n.get(i)??0)+1)}let o=null;for(const[r,i]of n)(o===null||i>(n.get(o)??0))&&(o=r);return o??t}function a(e,t){const n=e.find(r=>r.path===t);return n?n.surface:e.filter(r=>r.dynamic).map(r=>({route:r,stem:r.path.split(/[:*]/)[0]??""})).filter(({stem:r})=>r.length>1&&t.startsWith(r)).sort((r,i)=>i.stem.length-r.stem.length)[0]?.route.surface??null}function l(e,t){return u(e,"",new URLSearchParams({view:"frame",...t}))}function d(e){return e.reduce((t,n)=>t+n.tokens.length,0)}function x(e,t){return e.find(n=>n.id===t)??e[0]}export{w as MANIFEST_VERSION,c as byGroup,x as flowById,l as frameUrl,f as groupLabel,a as surfaceForRoute,p as surfaceFromPins,d as tokenCount,s as viewportById,u as workbenchUrl};
|
package/dist/manifest.types.d.ts
CHANGED
|
@@ -71,17 +71,25 @@ export type Origin = "config" | "spider";
|
|
|
71
71
|
export type FlowStep = {
|
|
72
72
|
label: string;
|
|
73
73
|
route: string;
|
|
74
|
+
via: string | null;
|
|
74
75
|
viewport: string;
|
|
75
76
|
note: string | null;
|
|
76
77
|
spec: string | null;
|
|
77
78
|
exists: boolean;
|
|
78
79
|
};
|
|
80
|
+
export type FlowBranch = {
|
|
81
|
+
id: string;
|
|
82
|
+
label: string;
|
|
83
|
+
from: number;
|
|
84
|
+
steps: Array<FlowStep>;
|
|
85
|
+
};
|
|
79
86
|
export type Flow = {
|
|
80
87
|
id: string;
|
|
81
88
|
title: string;
|
|
82
89
|
description: string | null;
|
|
83
90
|
origin: Origin;
|
|
84
91
|
steps: Array<FlowStep>;
|
|
92
|
+
branches: Array<FlowBranch>;
|
|
85
93
|
};
|
|
86
94
|
export type LearnedFile = {
|
|
87
95
|
file: string;
|
|
@@ -166,4 +174,4 @@ export type OverlayManifest = {
|
|
|
166
174
|
routes: Array<OverlayRoute>;
|
|
167
175
|
surfaces: Array<OverlaySurface>;
|
|
168
176
|
};
|
|
169
|
-
export declare const MANIFEST_VERSION =
|
|
177
|
+
export declare const MANIFEST_VERSION = 2;
|
package/dist/manifest.types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const o=
|
|
1
|
+
const o=2;export{o as MANIFEST_VERSION};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{useCallback as
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{useCallback as j,useRef as D,useState as d}from"react";import{ComponentPreview as G,ComponentScenarios as H,VariantScenarios as J,VerdictBadge as K}from"../component-preview";import{useManifest as Q}from"../config-context";import{useInspect as W}from"../edit-mode";import{InlineSurface as X,RouteFrame as F}from"../frame";import{frameUrl as Y,viewportById as S}from"../manifest";import{rowExtent as ee,ScreenFrame as R,useScale as te}from"../screen-frame";import{AUTO as I,ScreenToolbar as ie}from"../screen-toolbar";import{indexRegistry as ne}from"../registry";function ae({src:t,title:m,viewport:o,scale:c,editing:x,onLoaded:u}){const[g,b]=d(!1);return e(R,{viewport:o,scale:c,label:m,editing:x,children:g?e(F,{src:t,title:m,width:o.width,height:o.height,onLoad:u}):s("div",{className:"flex flex-col items-center justify-center gap-6 bg-zinc-50 dark:bg-zinc-900",style:{width:o.width,height:o.height},children:[e("p",{className:"max-w-lg px-10 text-center text-2xl leading-relaxed text-zinc-400 dark:text-zinc-500",children:"Cada vista es un iframe de la p\xE1gina aislada; se cargan al pedirlas para no multiplicar cargas del servidor."}),e("button",{type:"button",onClick:()=>b(!0),className:"rounded-xl border border-zinc-300 px-8 py-4 text-2xl font-medium text-zinc-600 hover:bg-zinc-100 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800",children:"Cargar esta vista"})]})})}function ge({entry:t,registry:m,componentIndex:o,editing:c,onPin:x,onHover:u,onToggleEdit:g,pinCount:b,onOpenRequest:V,showChrome:L,initialViewport:B,initialZoom:O,initialTheme:_}){const l=Q().config,[h,q]=d(B??I),[z,A]=d(O??"fit"),[p,M]=d(_??"light"),E=D(null),v=ne(m).get(t.id),f=h===I,a=f?null:S(l,h),{ref:P,scale:T}=te(z,[ee([a?.width??0])]),k=p==="split"?["light","dark"]:[p],[U,Z]=d(0),y=j(()=>Z(i=>i+1),[]);W(c,j(()=>E.current,[]),o,{onPin:x,onHover:u},`${t.id}:${h}:${z}:${p}:${U}`);const w=(i,n)=>Y(l,{component:t.id,viewport:a?.id??l.viewports[0]?.id??"",theme:i,...n?{scenario:n}:{}}),N=(i,n,r)=>s("section",{className:"mb-8",children:[s("header",{className:"mb-2 flex items-baseline gap-3",children:[e("h3",{className:"text-sm font-semibold text-zinc-900 dark:text-zinc-100",children:i}),n&&e("p",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",children:n})]}),r]}),$=(i,n,r)=>f?e(X,{theme:i,editing:c,children:n}):r?e(ae,{src:w(i,r),title:`${t.name} \xB7 ${r}`,viewport:a??S(l,void 0),scale:T,editing:c,onLoaded:y}):e(R,{viewport:a??S(l,void 0),scale:T,label:t.name,editing:c,children:e(F,{src:w(i),title:`${t.name} \xB7 ${a?.label??""}`,width:a?.width??0,height:a?.height??0},`${i}-${a?.id}`)});return s("div",{className:"flex h-full flex-col",children:[L&&e(ie,{viewport:h,onViewport:q,zoom:z,onZoom:A,theme:p,onTheme:M,zoomEnabled:!f,hint:f?"En Auto se dibuja en l\xEDnea: r\xE1pido, pero los breakpoints de Tailwind responden al ancho de la ventana, no al del cuadro.":`Dentro de un iframe a ${a?.width}px reales, as\xED que los breakpoints son de verdad.`,editing:c,onToggleEdit:g,pinCount:b,onOpenRequest:V,isolatedBase:{tab:"componentes",component:t.id}}),s("div",{ref:P,className:"min-h-0 flex-1 overflow-auto bg-zinc-50 p-6 dark:bg-zinc-950",children:[s("header",{className:"mb-5 max-w-2xl",children:[s("div",{className:"flex items-center gap-2",children:[e("h2",{className:"text-lg font-semibold text-zinc-900 dark:text-zinc-100",children:t.name}),e(K,{verdict:t.verdict})]}),e("p",{className:"mt-1 font-mono text-[11px] text-zinc-500 dark:text-zinc-400",children:t.file}),t.surface&&s("p",{className:"mt-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:["Superficie: ",e("span",{className:"font-medium",children:t.surface})]})]}),e("div",{ref:E,className:"space-y-8",children:k.map(i=>s("div",{children:[k.length>1&&e("p",{className:"mb-2 text-[11px] font-medium uppercase tracking-wider text-zinc-500",children:i==="light"?"Claro":"Oscuro"}),N("Vista principal",void 0,$(i,e(G,{entry:t,registry:v}))),e(J,{entry:t,registry:v,render:(n,r,C)=>N(n,r,$(i,C,n))}),e(H,{entry:t,registry:v,render:(n,r,C)=>N(n,r,$(i,C,n))})]},i))}),e("a",{href:w(k[0]??"light"),target:"_blank",rel:"noreferrer",className:"text-[11px] text-zinc-500 underline underline-offset-2 hover:text-zinc-900 dark:hover:text-zinc-100",children:"abrir aislado \u2197"})]})]})}export{ge as ComponentsPanel};
|
package/dist/panels/elements.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as n,Fragment as x}from"react/jsx-runtime";import{useState as p}from"react";import{useManifest as b}from"../config-context";import{cx as u}from"../cx";function
|
|
1
|
+
"use client";import{jsx as e,jsxs as n,Fragment as x}from"react/jsx-runtime";import{useState as p}from"react";import{useManifest as b}from"../config-context";import{cx as u}from"../cx";import{tokenCount as f}from"../manifest";function s({value:t}){return t?e("span",{className:"inline-block h-6 w-10 rounded border border-zinc-300 dark:border-zinc-600",style:{background:t},title:t}):e("span",{className:"inline-block h-6 w-10 rounded border border-dashed border-zinc-300 dark:border-zinc-600",title:"Sin declarar en este tema"})}function k({token:t}){const a=t.light===null||t.dark===null;return n("tr",{className:"border-b border-zinc-100 last:border-0 dark:border-zinc-800",children:[n("td",{className:"py-1.5 pr-4 align-middle",children:[e("code",{className:"font-mono text-[11px] text-zinc-700 dark:text-zinc-300",children:t.name}),a&&e("span",{className:"ml-2 rounded bg-amber-100 px-1 py-0.5 text-[10px] text-amber-900 dark:bg-amber-950 dark:text-amber-200",title:"Declarado en un solo tema",children:"falta un tema"}),t.note&&e("p",{className:"mt-0.5 text-[11px] text-zinc-500 dark:text-zinc-400",children:t.note})]}),t.kind==="color"?n(x,{children:[e("td",{className:"py-1.5 pr-3",children:e(s,{value:t.light})}),e("td",{className:"py-1.5 pr-3",children:e(s,{value:t.dark})})]}):e("td",{colSpan:2,className:"py-1.5 pr-3",children:e("code",{className:"font-mono text-[11px] text-zinc-500 dark:text-zinc-400",children:t.light??t.dark})})]})}function z({group:t}){return n("section",{id:`token-${t.id}`,className:"mb-8",children:[n("h3",{className:"mb-2 text-sm font-semibold text-zinc-900 dark:text-zinc-100",children:[t.label,e("span",{className:"ml-2 text-[11px] font-normal text-zinc-400",children:t.tokens.length})]}),n("table",{className:"w-full max-w-3xl border-collapse text-left",children:[e("thead",{children:n("tr",{className:"text-[10px] uppercase tracking-wider text-zinc-400",children:[e("th",{className:"pb-1 font-medium",children:"Token"}),e("th",{className:"pb-1 font-medium",children:"Claro"}),e("th",{className:"pb-1 font-medium",children:"Oscuro"})]})}),e("tbody",{children:t.tokens.map(a=>e(k,{token:a},a.name))})]})]})}function v(){const{tokens:t,config:a,stats:c}=b(),[l,d]=p(""),o=l.trim().toLowerCase(),i=o?t.map(r=>({...r,tokens:r.tokens.filter(h=>h.name.toLowerCase().includes(o))})).filter(r=>r.tokens.length>0):t,m=f(i);return n("div",{className:"flex h-full flex-col",children:[n("div",{className:"flex flex-wrap items-center gap-3 border-b border-zinc-200 bg-white px-6 py-2 dark:border-zinc-700 dark:bg-zinc-900",children:[e("input",{value:l,onChange:r=>d(r.target.value),placeholder:"Filtrar tokens\u2026",className:"w-56 rounded-md border border-zinc-300 px-2 py-1 text-[12px] text-zinc-800 placeholder:text-zinc-400 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-100"}),n("span",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",children:[m," tokens \xB7 ",a.title]})]}),e("div",{className:u("min-h-0 flex-1 overflow-auto bg-zinc-50 p-6 dark:bg-zinc-950"),children:t.length===0?c.missingStylesheet?n("p",{className:"max-w-lg text-sm text-zinc-600 dark:text-zinc-400",children:["El escaneo no encontr\xF3 la hoja de estilos"," ",e("code",{className:"font-mono",children:c.missingStylesheet}),", as\xED que no hay tokens que mostrar. Apunta ",e("code",{children:"themeSource"})," en",e("code",{className:"mx-1 font-mono",children:"workbench.config.json"})," al archivo con el bloque"," ",e("code",{children:"@theme"})," o ",e("code",{children:":root"}),"."]}):n("p",{className:"max-w-lg text-sm text-zinc-600 dark:text-zinc-400",children:["No se encontr\xF3 ning\xFAn token. Revisa ",e("code",{children:"themeSource"})," en",e("code",{className:"mx-1 font-mono",children:"workbench.config.json"}),": debe apuntar a la hoja de estilos con el bloque ",e("code",{children:"@theme"})," o ",e("code",{children:":root"}),"."]}):i.map(r=>e(z,{group:r},r.id))})]})}export{v as ElementsPanel};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { FlowStep, Viewport } from "../manifest.types";
|
|
3
|
+
export declare function Stage({ viewport, theme, className, children, }: {
|
|
4
|
+
viewport: Viewport;
|
|
5
|
+
theme: "light" | "dark";
|
|
6
|
+
className?: string;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
9
|
+
export declare function SpecCard({ step, viewport, theme, }: {
|
|
10
|
+
step: FlowStep;
|
|
11
|
+
viewport: Viewport;
|
|
12
|
+
theme: "light" | "dark";
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
export interface CardDraft {
|
|
15
|
+
route: string;
|
|
16
|
+
label: string;
|
|
17
|
+
spec: string;
|
|
18
|
+
via: string;
|
|
19
|
+
branchLabel: string;
|
|
20
|
+
}
|
|
21
|
+
export type CardStatus = "editing" | "writing" | {
|
|
22
|
+
error: string;
|
|
23
|
+
} | {
|
|
24
|
+
written: string | null;
|
|
25
|
+
};
|
|
26
|
+
export declare function NewScreenCard({ viewport, theme, fork, routesList, draft, status, onDraft, onSubmit, onCancel, }: {
|
|
27
|
+
viewport: Viewport;
|
|
28
|
+
theme: "light" | "dark";
|
|
29
|
+
fork: boolean;
|
|
30
|
+
routesList: string;
|
|
31
|
+
draft: CardDraft;
|
|
32
|
+
status: CardStatus;
|
|
33
|
+
onDraft: (changes: Partial<CardDraft>) => void;
|
|
34
|
+
onSubmit: () => void;
|
|
35
|
+
onCancel: () => void;
|
|
36
|
+
}): import("react").JSX.Element;
|
|
37
|
+
export declare function TailPlaceholder({ viewport, theme, writing, }: {
|
|
38
|
+
viewport: Viewport;
|
|
39
|
+
theme: "light" | "dark";
|
|
40
|
+
writing: boolean;
|
|
41
|
+
}): import("react").JSX.Element;
|
|
42
|
+
export declare const GHOST_WIDTH = 390;
|
|
43
|
+
export declare function GhostCard({ width, height, scale, label, disabled, onOpen, }: {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
scale: number;
|
|
47
|
+
label: string;
|
|
48
|
+
disabled: boolean;
|
|
49
|
+
onOpen: () => void;
|
|
50
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import"react";import{cx as b}from"../cx";import{framedWidth as N}from"../screen-frame";function h({viewport:a,theme:c,className:t,children:d}){return e("div",{className:b(c==="dark"&&"dark","bg-zinc-50 dark:bg-zinc-900",t),style:{width:a.width,height:a.height},children:d})}function w({step:a,viewport:c,theme:t}){return n(h,{viewport:c,theme:t,className:"flex flex-col gap-6 p-12 text-zinc-700 dark:text-zinc-200",children:[n("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[e("span",{className:"rounded-md border border-dashed border-amber-500 px-3 py-1 text-xl font-medium uppercase tracking-wider text-amber-700 dark:text-amber-300",children:"Por construir"}),e("span",{className:"break-all font-mono text-2xl text-zinc-500 dark:text-zinc-400",children:a.route})]}),e("h3",{className:"text-5xl font-semibold leading-tight text-zinc-900 dark:text-zinc-100",children:a.label}),e("p",{className:"max-w-3xl text-3xl leading-relaxed",children:a.spec??"Sin especificaci\xF3n todav\xEDa. A\xF1\xE1dela con la tarjeta al crear la pantalla, o con `spec` en workbench.config.json, para que este cuadro diga qu\xE9 debe hacer la pantalla."})]})}const x="mt-2 w-full rounded-md border border-zinc-300 bg-white px-4 py-3 text-3xl text-zinc-900 disabled:opacity-60 dark:border-zinc-600 dark:bg-zinc-800 dark:text-zinc-100",m="text-2xl font-medium uppercase tracking-wider text-zinc-400";function C({viewport:a,theme:c,fork:t,routesList:d,draft:i,status:l,onDraft:s,onSubmit:g,onCancel:u}){const p=typeof l=="object"&&"written"in l,o=l==="writing"||p,k=i.route.trim().length>0&&(!t||i.branchLabel.trim().length>0);return n(h,{viewport:a,theme:c,className:"flex flex-col gap-6 overflow-hidden p-12 text-zinc-700 dark:text-zinc-200",children:[n("div",{className:"flex flex-wrap items-center gap-x-4 gap-y-2",children:[e("span",{className:"rounded-md border border-dashed border-sky-500 px-3 py-1 text-xl font-medium uppercase tracking-wider text-sky-700 dark:text-sky-300",children:t?"Nueva rama":"Nueva pantalla"}),i.via.trim()&&n("span",{className:"text-2xl text-zinc-500 dark:text-zinc-400",children:["v\xEDa \xAB",i.via.trim(),"\xBB"]})]}),n("form",{className:"flex min-h-0 flex-1 flex-col gap-5",onSubmit:r=>{r.preventDefault(),g()},onKeyDown:r=>{r.key==="Escape"&&(r.stopPropagation(),u())},children:[t&&n("label",{className:"block",children:[e("span",{className:m,children:"Nombre de la rama"}),e("input",{value:i.branchLabel,onChange:r=>s({branchLabel:r.target.value}),placeholder:"Tier 2",disabled:o,className:x})]}),n("label",{className:"block",children:[e("span",{className:m,children:"Ruta"}),e("input",{value:i.route,onChange:r=>s({route:r.target.value}),list:d,placeholder:"/pantalla",autoFocus:!0,disabled:o,className:b(x,"font-mono")})]}),n("label",{className:"block",children:[e("span",{className:m,children:"Nombre"}),e("input",{value:i.label,onChange:r=>s({label:r.target.value}),placeholder:"Qu\xE9 pantalla es",disabled:o,className:x})]}),n("label",{className:"block",children:[e("span",{className:m,children:"Qu\xE9 debe hacer"}),e("textarea",{value:i.spec,onChange:r=>s({spec:r.target.value}),rows:4,placeholder:"Se muestra en el tablero mientras la p\xE1gina no exista.",disabled:o,className:b(x,"resize-none")})]}),typeof l=="object"&&"error"in l&&e("p",{role:"alert",className:"text-2xl leading-snug text-red-700 dark:text-red-300",children:l.error}),p&&e("p",{role:"status",className:"text-2xl text-emerald-700 dark:text-emerald-300",children:l.written??"Escrito \xB7 esperando el mapa\u2026"}),n("div",{className:"mt-auto flex items-center gap-4",children:[e("button",{type:"submit",disabled:o||!k,className:"rounded-md bg-zinc-900 px-6 py-3 text-2xl font-medium text-white disabled:opacity-40 dark:bg-zinc-100 dark:text-zinc-900",children:l==="writing"?"Escribiendo\u2026":"A\xF1adir"}),e("button",{type:"button",onClick:u,disabled:l==="writing",className:"rounded-md border border-zinc-300 px-6 py-3 text-2xl text-zinc-700 disabled:opacity-40 dark:border-zinc-600 dark:text-zinc-200",children:p?"Cerrar":"Cancelar"})]})]})]})}function j({viewport:a,theme:c,writing:t}){return e(h,{viewport:a,theme:c,className:"flex items-center justify-center",children:e("p",{className:"max-w-lg px-10 text-center text-2xl leading-relaxed text-zinc-400 dark:text-zinc-500",children:t?"Escribiendo\u2026":"Pantalla nueva \u2014 se edita en el tablero claro."})})}const E=390;function S({width:a,height:c,scale:t,label:d,disabled:i,onOpen:l}){return e("button",{type:"button",onClick:l,disabled:i,className:"flex shrink-0 items-center justify-center rounded-md border-2 border-dashed border-zinc-300 text-zinc-400 hover:border-sky-400 hover:text-sky-600 disabled:opacity-40 dark:border-zinc-700 dark:text-zinc-500 dark:hover:border-sky-500 dark:hover:text-sky-400",style:{width:N(a,t),height:Math.floor(c*t)},children:e("span",{className:"px-2 text-center text-sm font-medium",children:d})})}export{E as GHOST_WIDTH,S as GhostCard,C as NewScreenCard,w as SpecCard,h as Stage,j as TailPlaceholder};
|
package/dist/panels/flows.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ComponentIndex } from "../hover-inspect";
|
|
2
2
|
import type { Flow } from "../manifest.types";
|
|
3
|
-
import type
|
|
4
|
-
import type { Pin } from "../pin";
|
|
3
|
+
import { type PickTarget } from "../pick-highlight";
|
|
4
|
+
import type { Pin, SaveFlowInput, SaveFlowResult } from "../pin";
|
|
5
5
|
import { type Zoom } from "../screen-frame";
|
|
6
6
|
import { type ThemeMode } from "../screen-toolbar";
|
|
7
|
-
export declare function FlowsPanel({ flow, componentIndex, editing, onPin, onHover, onToggleEdit, pinCount, onOpenRequest, showChrome, initialViewport, initialZoom, initialTheme, }: {
|
|
7
|
+
export declare function FlowsPanel({ flow, componentIndex, editing, onPin, onHover, onToggleEdit, pinCount, onOpenRequest, showChrome, initialViewport, initialZoom, initialTheme, routes, onSaveFlow, }: {
|
|
8
8
|
flow: Flow;
|
|
9
9
|
componentIndex: ComponentIndex;
|
|
10
10
|
editing: boolean;
|
|
@@ -17,4 +17,6 @@ export declare function FlowsPanel({ flow, componentIndex, editing, onPin, onHov
|
|
|
17
17
|
initialViewport?: string;
|
|
18
18
|
initialZoom?: Zoom;
|
|
19
19
|
initialTheme?: ThemeMode;
|
|
20
|
+
routes?: string[];
|
|
21
|
+
onSaveFlow?: (input: SaveFlowInput) => Promise<SaveFlowResult>;
|
|
20
22
|
}): import("react").JSX.Element;
|
package/dist/panels/flows.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as t,Fragment as V,jsxs as c}from"react/jsx-runtime";import{Fragment as ue,useCallback as b,useEffect as W,useRef as Z,useState as v}from"react";import{useManifest as Y}from"../config-context";import{useInspect as me}from"../edit-mode";import{MirrorFrame as pe,RouteFrame as he}from"../frame";import{frameUrl as ge,viewportById as ee}from"../manifest";import{CAPTURE_TOTAL_MS as xe,captureMirror as fe,serializeMirror as ke}from"../mirror";import{FRAME_CHROME as be,ScreenFrame as ve,STEP_GUTTER as ze,useScale as Ne}from"../screen-frame";import{AUTO as G,CHIP as T,ScreenToolbar as $e}from"../screen-toolbar";const M={kind:"queued"};function je(n){return new Date(n).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function Ee({flow:n,steps:F,scale:p,theme:z,nonce:D,editing:q,slot:h,frames:_,active:N,onCapture:S,onActivate:L,onRefresh:R,onDemote:A,registerLiveFrame:x}){const{config:$}=Y();return t("div",{children:t("ol",{className:"flex items-start gap-4",children:F.map(({step:l,viewport:i},d)=>{const o=_[d]??M,j=N!==null&&N.step===d&&N.slot===h,m=o.kind==="capturing"&&h===0,U=j||o.kind==="restless"&&h===0||m;return c(ue,{children:[c("li",{className:"shrink-0",children:[t(ve,{viewport:i,scale:p,label:`${d+1}. ${l.label}`,editing:q,children:U?t(he,{src:l.route,title:`${n.title} \xB7 ${l.label}`,width:i.width,height:i.height,theme:z,frameRef:f=>x(d,h,f),onLoad:m?f=>S(d,f):void 0},D):o.kind==="mirrored"?t(pe,{srcdoc:o.srcdoc,title:`${n.title} \xB7 ${l.label} (espejo)`,width:i.width,height:i.height,theme:z}):t("div",{className:"flex items-center justify-center bg-zinc-50 dark:bg-zinc-900",style:{width:i.width,height:i.height},children:t("p",{className:"max-w-lg px-10 text-center text-2xl leading-relaxed text-zinc-400 dark:text-zinc-500",children:o.kind==="capturing"?"Cargando la ruta real\u2026":o.kind==="restless"?"Sin espejo \u2014 el paso sigue en vivo en el tablero claro.":"En cola \u2014 cada paso se carga una sola vez y queda como espejo."})})}),(j||o.kind==="mirrored"||o.kind==="restless"||m)&&t("div",{className:"mt-2 flex flex-wrap items-center gap-2",style:{width:Math.floor(i.width*p)},children:j?c(V,{children:[t("span",{className:"text-[11px] font-medium text-emerald-600 dark:text-emerald-400",children:"En vivo"}),t("button",{type:"button",className:T,onClick:A,children:"Volver a espejo"})]}):o.kind==="mirrored"?c(V,{children:[c("span",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",title:"Espejo est\xE1tico de la p\xE1gina real \u2014 sin peticiones al servidor.",children:["Espejo \xB7 ",je(o.capturedAt)]}),t("button",{type:"button",className:T,onClick:()=>L(d,h),title:"Monta la p\xE1gina real para interactuar con ella.",children:"Activar"}),t("button",{type:"button",className:T,onClick:()=>R(d),title:"Vuelve a cargar la ruta y captura un espejo nuevo.",children:"Actualizar"})]}):o.kind==="restless"?c(V,{children:[t("span",{className:"text-[11px] text-amber-600 dark:text-amber-400",title:"La p\xE1gina no termin\xF3 de asentarse, as\xED que el cuadro sigue en vivo.",children:"En vivo \u2014 sin espejo"}),t("button",{type:"button",className:T,onClick:()=>R(d),children:"Reintentar espejo"})]}):t("span",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",children:"Cargando\u2026"})}),c("div",{className:"mt-2 flex items-start justify-between gap-2",style:{width:Math.floor(i.width*p)},children:[l.note&&t("p",{className:"text-[11px] leading-snug text-zinc-500 dark:text-zinc-400",children:l.note}),c("span",{className:"ml-auto flex shrink-0 items-center gap-2",children:[c("a",{href:l.route,target:"_blank",rel:"noreferrer",className:"font-mono text-[11px] text-zinc-500 underline underline-offset-2 hover:text-zinc-900 dark:hover:text-zinc-100",children:[l.route," \u2197"]}),t("a",{href:ge($,{route:l.route,viewport:i.id,theme:z}),target:"_blank",rel:"noreferrer",className:"text-[11px] text-zinc-500 underline underline-offset-2 hover:text-zinc-900 dark:hover:text-zinc-100",children:"aislado \u2197"})]})]})]}),d<F.length-1&&t("li",{"aria-hidden":!0,className:"shrink-0 self-center text-xl text-zinc-400 dark:text-zinc-600",children:"\u2192"})]},`${n.id}-${d}-${l.route}`)})})})}function qe({flow:n,componentIndex:F,editing:p,onPin:z,onHover:D,onToggleEdit:q,pinCount:h,onOpenRequest:_,showChrome:N,initialViewport:S,initialZoom:L,initialTheme:R}){const{config:A,stats:x}=Y(),[$,l]=v(0),[i,d]=v(S??G),[o,j]=v(L??"fit"),[m,U]=v(R??"light"),f=Z(null),[g,k]=v(()=>n.steps.map(()=>M)),[u,H]=v(null),I=Z(new Map);W(()=>{k(n.steps.map(()=>M)),H(null)},[$]);const Q=Z(1);W(()=>{g.some(e=>e.kind==="capturing")||g.some(e=>e.kind==="queued")&&k(e=>{if(e.some(a=>a.kind==="capturing"))return e;const r=e.findIndex(a=>a.kind==="queued");if(r===-1)return e;const s=Q.current;return Q.current+=1,e.map((a,w)=>w===r?{kind:"capturing",ticket:s}:a)})},[g]);const E=g.findIndex(e=>e.kind==="capturing"),J=E===-1?null:g[E],O=J?.kind==="capturing"?J.ticket:null;W(()=>{if(E===-1||O===null)return;const e=setTimeout(()=>{k(r=>r.map((s,a)=>a===E&&s.kind==="capturing"&&s.ticket===O?{kind:"restless"}:s))},xe);return()=>clearTimeout(e)},[E,O]);const te=b((e,r)=>{const s=n.steps[e]?.route;s&&fe(r,s).then(a=>{k(w=>w.map((C,P)=>P!==e||C.kind!=="capturing"?C:a?{kind:"mirrored",srcdoc:a,capturedAt:Date.now()}:{kind:"restless"}))}).catch(()=>{})},[n]),B=b(()=>{if(!u)return;const e=I.current.get(`${u.slot}:${u.step}`),r=n.steps[u.step]?.route;if(e&&r)try{const s=e.contentDocument;if(s){const a=e.contentWindow?.location.pathname??r,w=ke(s,a,window.location.origin),C=Date.now(),P=u.step;k(oe=>oe.map((le,de)=>de===P?{kind:"mirrored",srcdoc:w,capturedAt:C}:le))}}catch{}H(null)},[u,n]),ne=b((e,r)=>{B(),H({step:e,slot:r})},[B]),re=b(e=>{k(r=>r.map((s,a)=>a===e?M:s))},[]),ae=b((e,r,s)=>{const a=`${r}:${e}`;s?I.current.set(a,s):I.current.delete(a)},[]),K=i===G?null:ee(A,i),y=n.steps.map(e=>({step:e,viewport:K??ee(A,e.viewport)})),ie=y.reduce((e,{viewport:r})=>e+r.width,0),{ref:se,scale:ce}=Ne(o,ie,y.length*be+Math.max(0,y.length-1)*ze),X=m==="split"?["light","dark"]:[m];return me(p,b(()=>f.current,[]),F,{onPin:z,onHover:D},`${n.id}:${$}:${i}:${o}:${m}:${g.map(e=>e.kind.charAt(0)).join("")}:${u?`${u.slot}.${u.step}`:"-"}`),c("div",{className:"flex h-full flex-col",children:[N&&t($e,{viewport:i,onViewport:d,zoom:o,onZoom:j,theme:m,onTheme:U,actions:t("button",{type:"button",onClick:()=>l(e=>e+1),className:T,children:"Recargar cuadros"}),hint:i===G?"Rutas reales, cargadas de una en una y congeladas como espejos; activa un paso para interactuar. Las pantallas con sesi\xF3n requieren haber iniciado sesi\xF3n aqu\xED.":`Rutas reales, los ${y.length} pasos a ${K?.width}px, congeladas como espejos.`,editing:p,onToggleEdit:q,pinCount:h,onOpenRequest:_,isolatedBase:{tab:"flujos",flow:n.id}}),c("div",{ref:se,className:"min-h-0 flex-1 overflow-auto bg-zinc-50 p-6 dark:bg-zinc-950",children:[c("header",{className:"mb-5 max-w-2xl",children:[c("div",{className:"flex items-center gap-2",children:[t("h2",{className:"text-lg font-semibold text-zinc-900 dark:text-zinc-100",children:n.title}),n.origin==="spider"&&t("span",{className:"rounded bg-zinc-100 px-1.5 py-0.5 text-[10px] font-medium text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300",title:"Descubierto siguiendo los enlaces reales de la app. Declara el recorrido en workbench.config.json para darle nombre y notas.",children:"descubierto"})]}),n.description&&t("p",{className:"mt-1 text-sm text-zinc-600 dark:text-zinc-400",children:n.description}),x.untraceableHrefs>0&&c("p",{className:"mt-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:[x.untraceableHrefs," enlaces con destino calculado no se pudieron rastrear, as\xED que puede faltar alg\xFAn paso."]}),x.droppedFlows>0&&c("p",{className:"mt-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:[x.droppedFlows," recorridos adicionales encontrados y no mostrados; declara los que importen en workbench.config.json."]})]}),t("div",{ref:f,children:t("div",{className:"space-y-8",children:X.map((e,r)=>c("div",{children:[X.length>1&&t("p",{className:"mb-2 text-[11px] font-medium uppercase tracking-wider text-zinc-500",children:e==="light"?"Claro":"Oscuro"}),t(Ee,{flow:n,steps:y,scale:ce,theme:e,nonce:$,editing:p,slot:r,frames:g,active:u,onCapture:te,onActivate:ne,onRefresh:re,onDemote:B,registerLiveFrame:ae})]},r===0?"a":"b"))})})]})]})}export{qe as FlowsPanel};
|
|
1
|
+
"use client";import{jsx as r,jsxs as o,Fragment as Z}from"react/jsx-runtime";import{Fragment as Ye,useCallback as M,useEffect as O,useMemo as me,useRef as fe,useState as C}from"react";import{useManifest as $e}from"../config-context";import{ConnectPopover as Je}from"../connect-popover";import{useInspect as Xe}from"../edit-mode";import{appendStep as et,bodyOf as he,forkFrom as tt,forkResolvesTo as nt,hasStepAt as rt,isForkPoint as at,removeLast as it,routeOfHref as je,stepInputOf as st}from"../flow-edit";import{frameOf as ke,NO_FRAMES as Fe,nextCapture as Re,prune as ot,withFrame as Q}from"../flow-frames";import{forkPrefix as Te,laneKey as xe,layOut as lt,rowExtents as ct}from"../flow-layout";import{MirrorFrame as dt,RouteFrame as ut}from"../frame";import{frameUrl as pt,viewportById as ae}from"../manifest";import{CAPTURE_TOTAL_MS as mt,captureMirror as ft,serializeMirror as ht}from"../mirror";import{Outline as kt}from"../pick-highlight";import{framedWidth as Le,rowWidth as Ae,ScreenFrame as be,STEP_GUTTER as Se,useScale as xt}from"../screen-frame";import{AUTO as ge,CHIP as L,ScreenToolbar as bt}from"../screen-toolbar";import{GHOST_WIDTH as ve,GhostCard as gt,NewScreenCard as De,SpecCard as vt,Stage as wt,TailPlaceholder as Ve}from"./flow-cards";function yt(i){return new Date(i).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}const Be={route:"",label:"",spec:"",via:"",branchLabel:""};function Oe(i){return i.kind==="trunk"?{kind:"trunk"}:{kind:"branch",index:i.index,id:i.id}}function we(i){return xe(i.kind==="trunk"?null:i.id)}function Nt({flow:i,lanes:I,scale:m,theme:g,nonce:ie,editing:Y,slot:E,frames:se,active:G,onCapture:oe,onActivate:le,onRefresh:J,onDemote:ce,registerLiveFrame:A,composer:n}){const{config:P}=$e();return o("div",{className:"space-y-6",children:[I.map(s=>{const X=s.kind==="branch"&&s.fork!==null?Ae(Te(I,s.fork),m)+Se:0,$=Oe(s),q=n?.card&&!n.card.at.fork&&we(n.card.at.lane)===we($)?n.card:null,S=s.nodes[s.nodes.length-1];return o("div",{className:"w-max",style:X>0?{marginLeft:X}:void 0,children:[s.kind==="branch"&&o("p",{className:"mb-2 whitespace-nowrap text-[11px] font-medium text-zinc-500 dark:text-zinc-400",children:[r("span",{"aria-hidden":!0,children:"\u21B3 "}),s.label," \xB7 desde el paso ",s.from+1,s.nodes[0]?.step.via&&` \xB7 v\xEDa \xAB${s.nodes[0].step.via}\xBB`,s.fork===null&&" \u2014 ese paso no est\xE1 en el tronco"]}),o("ol",{className:"flex items-start gap-4","aria-label":s.kind==="trunk"?"Tronco":`${s.label}, desde el paso ${s.from+1}`,children:[s.nodes.map((f,v)=>{const{step:h,viewport:k}=f,c=ke(se,f),R=G!==null&&G.key===f.key&&G.slot===E,y=c.kind==="capturing"?c.ticket:null,d=y!==null&&E===0,D=R||c.kind==="restless"&&E===0||d,j=v===s.nodes.length-1,x=s.nodes[v+1]?.step.via;return o(Ye,{children:[o("li",{className:"shrink-0",children:[r(be,{viewport:k,scale:m,label:`${f.number}. ${h.label}`,editing:Y&&c.kind!=="unbuilt",children:c.kind==="unbuilt"?r(vt,{step:h,viewport:k,theme:g}):D?r(ut,{src:h.route,title:`${i.title} \xB7 ${h.label}`,width:k.width,height:k.height,theme:g,frameRef:b=>A(f.key,E,b),onLoad:d&&y!==null?b=>oe(f.key,y,b):void 0},ie):c.kind==="mirrored"?r(dt,{srcdoc:c.srcdoc,title:`${i.title} \xB7 ${h.label} (espejo)`,width:k.width,height:k.height,theme:g,connect:n?.connect&&!Y?{onPick:b=>n.onPick(f,b),onHover:b=>n.onHoverPick(f,b)}:void 0}):r(wt,{viewport:k,theme:g,className:"flex items-center justify-center",children:r("p",{className:"max-w-lg px-10 text-center text-2xl leading-relaxed text-zinc-400 dark:text-zinc-500",children:c.kind==="capturing"?"Cargando la ruta real\u2026":c.kind==="restless"?"Sin espejo \u2014 el paso sigue en vivo en el tablero claro.":"En cola \u2014 cada paso se carga una sola vez y queda como espejo."})})}),(R||c.kind==="mirrored"||c.kind==="restless"||c.kind==="unbuilt"||d)&&o("div",{className:"mt-2 flex flex-wrap items-center gap-2",style:{width:Le(k.width,m)},children:[c.kind==="unbuilt"?r("span",{className:"text-[11px] text-amber-700 dark:text-amber-300",title:"La ruta no existe todav\xEDa; el cuadro muestra la especificaci\xF3n. Se vuelve un espejo real en el siguiente `workbench scan` despu\xE9s de que la p\xE1gina aterrice.",children:"Sin p\xE1gina todav\xEDa"}):R?o(Z,{children:[r("span",{className:"text-[11px] font-medium text-emerald-600 dark:text-emerald-400",children:"En vivo"}),r("button",{type:"button",className:L,onClick:ce,children:"Volver a espejo"})]}):c.kind==="mirrored"?o(Z,{children:[o("span",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",title:"Espejo est\xE1tico de la p\xE1gina real \u2014 sin peticiones al servidor.",children:["Espejo \xB7 ",yt(c.capturedAt)]}),r("button",{type:"button",className:L,onClick:()=>le(f.key,E),title:"Monta la p\xE1gina real para interactuar con ella.",children:"Activar"}),r("button",{type:"button",className:L,onClick:()=>J(f.key),title:"Vuelve a cargar la ruta y captura un espejo nuevo.",children:"Actualizar"})]}):c.kind==="restless"?o(Z,{children:[r("span",{className:"text-[11px] text-amber-700 dark:text-amber-300",title:"La p\xE1gina no termin\xF3 de asentarse, as\xED que el cuadro sigue en vivo.",children:"En vivo \u2014 sin espejo"}),r("button",{type:"button",className:L,onClick:()=>J(f.key),children:"Reintentar espejo"})]}):r("span",{className:"text-[11px] text-zinc-500 dark:text-zinc-400",children:"Cargando\u2026"}),n&&s.kind==="trunk"&&r("button",{type:"button",className:L,disabled:n.busy||n.card!==null,onClick:()=>n.onFork(v,f.flat,f.step.route),title:"Empieza una rama desde este paso.",children:"+ rama"}),n&&j&&(s.kind==="branch"||s.nodes.length>1)&&(s.kind==="trunk"&&at(i,v)?r("button",{type:"button",className:`${L} opacity-40`,"aria-disabled":"true",onClick:()=>{},title:"Este paso tiene ramas; qu\xEDtalas primero.",children:"quitar"}):r("button",{type:"button",className:L,disabled:n.busy||n.card!==null,onClick:()=>n.onRemove($),title:"Quita esta pantalla del recorrido.",children:"quitar"}))]}),o("div",{className:"mt-2 flex items-start justify-between gap-2",style:{width:Le(k.width,m)},children:[h.note&&r("p",{className:"text-[11px] leading-snug text-zinc-500 dark:text-zinc-400",children:h.note}),r("span",{className:"ml-auto flex shrink-0 items-center gap-2",children:c.kind!=="unbuilt"?o(Z,{children:[o("a",{href:h.route,target:"_blank",rel:"noreferrer",className:"font-mono text-[11px] text-zinc-500 underline underline-offset-2 hover:text-zinc-900 dark:hover:text-zinc-100",children:[h.route," \u2197"]}),r("a",{href:pt(P,{route:h.route,viewport:k.id,theme:g}),target:"_blank",rel:"noreferrer",className:"text-[11px] text-zinc-500 underline underline-offset-2 hover:text-zinc-900 dark:hover:text-zinc-100",children:"aislado \u2197"})]}):r("span",{className:"font-mono text-[11px] text-zinc-400 dark:text-zinc-500",children:h.route})})]})]}),v<s.nodes.length-1&&o("li",{"aria-hidden":x?void 0:!0,className:"relative shrink-0 self-center text-xl text-zinc-400 dark:text-zinc-600",children:[r("span",{"aria-hidden":!0,children:"\u2192"}),x&&o("span",{className:"absolute left-1/2 top-full mt-0.5 -translate-x-1/2 whitespace-nowrap text-[10px] text-zinc-500 dark:text-zinc-400",children:["\xAB",x,"\xBB"]})]})]},`${v}:${h.route}`)}),n&&o(Z,{children:[r("li",{"aria-hidden":!0,className:"shrink-0 self-center text-xl text-zinc-300 dark:text-zinc-700",children:"\u2192"}),r("li",{className:"shrink-0",children:q&&n.cardViewport?r(be,{viewport:n.cardViewport,scale:m,label:"Nueva pantalla",children:E===0?r(De,{viewport:n.cardViewport,theme:g,fork:!1,routesList:n.routesList,draft:q.draft,status:q.status,onDraft:n.onDraft,onSubmit:n.onSubmit,onCancel:n.onCancelCard}):r(Ve,{viewport:n.cardViewport,theme:g,writing:q.status==="writing"})}):r(gt,{width:ve,height:S?.viewport.height??844,scale:m,label:"+ A\xF1adir pantalla",disabled:n.busy||n.card!==null,onOpen:()=>n.onGhost($,s.nodes.length-1,S?.flat??0,S?.step.route??"")})})]})]})]},s.kind==="trunk"?"trunk":`branch:${s.id}`)}),n?.card?.at.fork&&n.cardViewport&&o("div",{className:"w-max",style:{marginLeft:Ae(Te(I,n.card.at.flat),m)+Se},children:[o("p",{className:"mb-2 whitespace-nowrap text-[11px] font-medium text-sky-600 dark:text-sky-400",children:[r("span",{"aria-hidden":!0,children:"\u21B3 "}),n.card.draft.branchLabel.trim()||"nueva rama"," \xB7 desde el paso"," ",n.card.at.after+1,nt(i,i.steps[n.card.at.after]?.route??"")!==n.card.at.after&&" \u2014 el tronco repite esta ruta; el motor dibuja la rama desde su primera aparici\xF3n"]}),r("ol",{className:"flex items-start gap-4","aria-label":"Nueva rama",children:r("li",{className:"shrink-0",children:r(be,{viewport:n.cardViewport,scale:m,label:"Nueva pantalla",children:E===0?r(De,{viewport:n.cardViewport,theme:g,fork:!0,routesList:n.routesList,draft:n.card.draft,status:n.card.status,onDraft:n.onDraft,onSubmit:n.onSubmit,onCancel:n.onCancelCard}):r(Ve,{viewport:n.cardViewport,theme:g,writing:n.card.status==="writing"})})})})]})]})}const Pe="workbench-flow-routes";function Pt({flow:i,componentIndex:I,editing:m,onPin:g,onHover:ie,onToggleEdit:Y,pinCount:E,onOpenRequest:se,showChrome:G,initialViewport:oe,initialZoom:le,initialTheme:J,routes:ce,onSaveFlow:A}){const{config:n,stats:P}=$e(),[s,X]=C(0),[$,q]=C(oe??ge),[S,f]=C(le??"fit"),[v,h]=C(J??"light"),k=fe(null),c=$===ge?null:ae(n,$),R=ae(n,void 0).id,{lanes:y,nodes:d}=me(()=>lt(i,e=>c??ae(n,e)),[i,c,n]),[D,j]=C(Fe),[x,b]=C(null),de=fe(new Map);O(()=>{j(Fe),b(null)},[s]);const ye=d.map(e=>e.key).join("|");O(()=>{j(e=>ot(e,d)),b(e=>e&&d.some(t=>t.key===e.key)?e:null)},[ye]);const Ne=fe(1);O(()=>{const e=Re(D,d);e!==null&&j(t=>{if(Re(t,d)!==e)return t;const a=Ne.current;return Ne.current+=1,Q(t,e,{kind:"capturing",ticket:a})})},[D,d]);let ee=null,te=null;for(const e of d){const t=ke(D,e);if(t.kind==="capturing"){ee=e.key,te=t.ticket;break}}O(()=>{if(ee===null||te===null)return;const e=ee,t=te,a=setTimeout(()=>{j(l=>{const u=l.get(e);return u?.kind==="capturing"&&u.ticket===t?Q(l,e,{kind:"restless"}):l})},mt);return()=>clearTimeout(a)},[ee,te]);const qe=M((e,t,a)=>{const l=d.find(u=>u.key===e)?.step.route;l&&ft(a,l).then(u=>{j(F=>{const p=F.get(e);return p?.kind!=="capturing"||p.ticket!==t?F:Q(F,e,u?{kind:"mirrored",srcdoc:u,capturedAt:Date.now()}:{kind:"restless"})})}).catch(()=>{})},[d]),ue=M(()=>{if(!x)return;const e=de.current.get(`${x.slot}:${x.key}`),t=d.find(a=>a.key===x.key)?.step.route;if(e&&t)try{const a=e.contentDocument;if(a){const l=e.contentWindow?.location.pathname??t,u=ht(a,l,window.location.origin),F=Date.now(),p=x.key;j(B=>Q(B,p,{kind:"mirrored",srcdoc:u,capturedAt:F}))}}catch{}b(null)},[x,d]),He=M((e,t)=>{ue(),b({key:e,slot:t})},[ue]),_e=M(e=>{j(t=>Q(t,e,{kind:"queued"}))},[]),Me=M((e,t,a)=>{const l=`${t}:${e}`;a?de.current.set(l,a):de.current.delete(l)},[]),U=!!A,[w,N]=C(null),[ne,H]=C(null),[V,T]=C(null),[K,re]=C(null),pe=w!==null&&typeof w.status=="object"&&"written"in w.status&&w.status.written===null&&rt(i,w.at,w.draft.route.trim());O(()=>{pe&&N(null)},[pe]);const z=w&&!pe?w:null,W=z?c??d.find(e=>e.flat===z.at.flat)?.viewport??ae(n,void 0):null,Ie=z?.status==="writing"||ne!==null&&ne.error===null;O(()=>{m&&(T(null),re(null))},[m]),O(()=>{T(null),re(null),H(e=>e&&e.error===null?null:e)},[ye,s]);const ze=e=>{for(const t of y){const a=t.nodes.findIndex(l=>l.key===e);if(a!==-1)return{ref:Oe(t),kind:t.kind,position:a,isLast:a===t.nodes.length-1}}return null},Ge=async()=>{if(!w||!A||w.status==="writing")return;const{at:e,draft:t}=w,a=e.lane.kind==="trunk"?i.steps[e.after]:i.branches[e.lane.index]?.id===e.lane.id?i.branches[e.lane.index]?.steps[e.after]:void 0;if(!a||a.route!==e.anchorRoute){N(p=>p&&{...p,status:{error:"El recorrido cambi\xF3 debajo de la tarjeta; ci\xE9rrala y vuelve a a\xF1adir la pantalla."}});return}const l=a.viewport,u=st(t,l===R?"":l),F=e.fork?tt(he(i,R),a.route,t.branchLabel.trim(),u):et(he(i,R),e.lane,u);N(p=>p&&{...p,status:"writing"});try{const p=await A({...F,id:i.id});N(B=>B&&{...B,status:p.ok?{written:p.note??null}:{error:p.error??"Fall\xF3 la escritura."}})}catch(p){N(B=>B&&{...B,status:{error:p instanceof Error?p.message:"Fall\xF3 la escritura."}})}},Ue=U?{card:z,cardViewport:W,routesList:Pe,busy:Ie,onDraft:e=>N(t=>t&&{...t,status:"editing",draft:{...t.draft,...e}}),onSubmit:()=>{Ge()},onCancelCard:()=>N(null),onGhost:(e,t,a,l)=>{T(null),N({at:{lane:e,after:t,anchorRoute:l,fork:!1,flat:a},draft:Be,status:"editing"})},onFork:(e,t,a)=>{T(null),N({at:{lane:{kind:"trunk"},after:e,anchorRoute:a,fork:!0,flat:t},draft:Be,status:"editing"})},onRemove:e=>{if(!A)return;const t=e.kind==="trunk"?e:(()=>{const a=i.branches.findIndex(l=>l.id===e.id);return a===-1?null:{kind:"branch",index:a,id:e.id}})();if(!t){H({error:"El recorrido cambi\xF3; esa fila ya no existe."});return}H({error:null}),A({...it(he(i,R),t),id:i.id}).then(a=>{a.ok?a.note&&H({error:a.note}):H({error:a.error??"Fall\xF3 la escritura."})}).catch(a=>H({error:a instanceof Error?a.message:"Fall\xF3 la escritura."}))},connect:!m,onPick:(e,t)=>{if(!t){T(null);return}const a=ze(e.key);if(!a)return;const l=je(t.href,window.location.origin),u=a.isLast?"append":a.kind==="trunk"?"fork":"blocked";T({node:e,pick:t,route:l,mode:u}),re(null)},onHoverPick:(e,t)=>{re(t?{pick:t,route:je(t.href,window.location.origin)}:null)}}:null,Ke=()=>{if(!V)return;const{node:e,pick:t,route:a,mode:l}=V,u=ze(e.key);if(T(null),!u||l==="blocked")return;const F={route:a??"",label:t.text,spec:"",via:t.text,branchLabel:t.text},p=l==="fork"?{lane:{kind:"trunk"},after:u.position,anchorRoute:e.step.route,fork:!0,flat:e.flat}:{lane:u.ref,after:u.position,anchorRoute:e.step.route,fork:!1,flat:e.flat};N({at:p,draft:F,status:"editing"})},Ce=me(()=>{if(!U)return;const e=new Map;for(const t of y){const a=t.kind==="trunk"?xe(null):xe(t.id),l=z&&!z.at.fork&&we(z.at.lane)===a?W?.width??ve:ve;e.set(a,l)}return{tail:e,forkRow:z?.at.fork&&W?{fork:z.at.flat,width:W.width}:null}},[U,y,z,W]),We=me(()=>ct(y,Ce),[y,Ce]),{ref:Ze,scale:Qe}=xt(S,We),Ee=v==="split"?["light","dark"]:[v];Xe(m,M(()=>k.current,[]),I,{onPin:g,onHover:ie},`${i.id}:${s}:${$}:${S}:${v}:${d.map(e=>ke(D,e).kind.charAt(0)).join("")}:${x?`${x.slot}.${x.key}`:"-"}`);const _=d.filter(e=>!e.step.exists).length;return o("div",{className:"flex h-full flex-col",children:[G&&r(bt,{viewport:$,onViewport:q,zoom:S,onZoom:f,theme:v,onTheme:h,actions:r("button",{type:"button",onClick:()=>X(e=>e+1),className:L,children:"Recargar cuadros"}),hint:$===ge?"Rutas reales, cargadas de una en una y congeladas como espejos; activa un paso para interactuar. Las pantallas con sesi\xF3n requieren haber iniciado sesi\xF3n aqu\xED.":`Rutas reales, los ${d.length-_} pasos a ${c?.width}px, congeladas como espejos${_>0?`; ${_} por construir`:""}.`,editing:m,onToggleEdit:Y,pinCount:E,onOpenRequest:se,isolatedBase:{tab:"flujos",flow:i.id}}),o("div",{ref:Ze,className:"min-h-0 flex-1 overflow-auto bg-zinc-50 p-6 dark:bg-zinc-950",children:[o("header",{className:"mb-5 max-w-2xl",children:[o("div",{className:"flex items-center gap-2",children:[r("h2",{className:"text-lg font-semibold text-zinc-900 dark:text-zinc-100",children:i.title}),i.origin==="spider"&&r("span",{className:"rounded bg-zinc-100 px-1.5 py-0.5 text-[10px] font-medium text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300",title:"Descubierto siguiendo los enlaces reales de la app. A\xF1\xE1dele una pantalla y queda declarado en workbench.config.json con este mismo id.",children:"descubierto"}),i.branches.length>0&&o("span",{className:"rounded bg-zinc-100 px-1.5 py-0.5 text-[10px] font-medium text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300",children:[i.branches.length," ",i.branches.length===1?"rama":"ramas"]})]}),i.description&&r("p",{className:"mt-1 text-sm text-zinc-600 dark:text-zinc-400",children:i.description}),U&&r("p",{className:"mt-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:"Haz clic en un bot\xF3n o enlace de un espejo para a\xF1adir la pantalla a la que lleva; cada fila termina en \xAB+ A\xF1adir pantalla\xBB."}),ne?.error&&r("p",{role:"alert",className:"mt-1 text-[11px] text-red-700 dark:text-red-300",children:ne.error}),_>0&&o("p",{className:"mt-1 text-[11px] text-amber-700 dark:text-amber-300",children:[_," ",_===1?"paso por construir":"pasos por construir"," \u2014 se muestran sus especificaciones; se vuelven espejos reales cuando sus p\xE1ginas aterricen."]}),P.untraceableHrefs>0&&o("p",{className:"mt-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:[P.untraceableHrefs," enlaces con destino calculado no se pudieron rastrear, as\xED que puede faltar alg\xFAn paso."]}),P.droppedFlows>0&&o("p",{className:"mt-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:[P.droppedFlows," recorridos adicionales encontrados y no mostrados; declara los que importen en workbench.config.json."]})]}),U&&r("datalist",{id:Pe,children:(ce??[]).map(e=>r("option",{value:e},e))}),r("div",{ref:k,tabIndex:-1,children:r("div",{className:"space-y-8",children:Ee.map((e,t)=>o("div",{children:[Ee.length>1&&r("p",{className:"mb-2 text-[11px] font-medium uppercase tracking-wider text-zinc-500",children:e==="light"?"Claro":"Oscuro"}),r(Nt,{flow:i,lanes:y,scale:Qe,theme:e,nonce:s,editing:m,slot:t,frames:D,active:x,onCapture:qe,onActivate:He,onRefresh:_e,onDemote:ue,registerLiveFrame:Me,composer:Ue})]},t===0?"a":"b"))})})]}),K&&!V&&!m&&r(kt,{rect:K.pick.rect,tone:"sky",label:`\xAB${K.pick.text||"control"}\xBB${K.route?` \u2192 ${K.route}`:""}`}),V&&r(Je,{pick:V.pick,route:V.route,mode:V.mode,onConfirm:Ke,onCancel:()=>{T(null),k.current?.focus()}})]})}export{Pt as FlowsPanel};
|
package/dist/pick-highlight.d.ts
CHANGED
|
@@ -15,6 +15,27 @@ export declare function mapRect(element: Element, frame: HTMLIFrameElement | nul
|
|
|
15
15
|
height: number;
|
|
16
16
|
};
|
|
17
17
|
export declare function describeNode(node: ResolvedNode): string;
|
|
18
|
+
declare const TONES: {
|
|
19
|
+
readonly amber: {
|
|
20
|
+
readonly border: "border-amber-400";
|
|
21
|
+
readonly tag: "bg-amber-400 text-amber-950";
|
|
22
|
+
};
|
|
23
|
+
readonly sky: {
|
|
24
|
+
readonly border: "border-sky-400";
|
|
25
|
+
readonly tag: "bg-sky-400 text-sky-950";
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export declare function Outline({ rect, label, tone, }: {
|
|
29
|
+
rect: {
|
|
30
|
+
top: number;
|
|
31
|
+
left: number;
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
};
|
|
35
|
+
label: string;
|
|
36
|
+
tone?: keyof typeof TONES;
|
|
37
|
+
}): import("react").JSX.Element;
|
|
18
38
|
export declare function PickHighlight({ target }: {
|
|
19
39
|
target: PickTarget | null;
|
|
20
40
|
}): import("react").JSX.Element | null;
|
|
41
|
+
export {};
|
package/dist/pick-highlight.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as s,jsxs as h}from"react/jsx-runtime";import{cx as c}from"./cx";import{SCALE_ATTR as p}from"./screen-frame";const l=20;function x(t,o){const e=t.getBoundingClientRect();if(!o)return{top:e.top,left:e.left,width:e.width,height:e.height};const n=o.closest(`[${p}]`)?.getAttribute(p),r=Number(n),i=Number.isFinite(r)&&r>0?r:1,a=o.getBoundingClientRect();return{top:a.top+e.top*i,left:a.left+e.left*i,width:e.width*i,height:e.height*i}}function u(t){const o=t.component??`<${t.tag}>`,e=t.component&&t.file?t.file.split("/").pop():null;return[o,e,t.surface].filter(Boolean).join(" \xB7 ")}const d={amber:{border:"border-amber-400",tag:"bg-amber-400 text-amber-950"},sky:{border:"border-sky-400",tag:"bg-sky-400 text-sky-950"}};function f({rect:t,label:o,tone:e="amber"}){const n=t.top>l+4;return h("div",{"aria-hidden":!0,className:"pointer-events-none fixed z-[2147483000]",style:{top:t.top,left:t.left,width:t.width,height:t.height},children:[s("div",{className:c("absolute inset-0 border",d[e].border)}),s("span",{className:c("absolute left-0 whitespace-nowrap rounded-sm px-1.5 py-0.5 font-mono text-[10px] leading-none shadow-sm",d[e].tag),style:n?{top:-l}:{bottom:-l},children:o})]})}function w({target:t}){return t?s(f,{rect:t.rect,label:u(t.node)}):null}export{f as Outline,w as PickHighlight,u as describeNode,x as mapRect};
|
package/dist/pin.d.ts
CHANGED
|
@@ -37,3 +37,37 @@ export interface TicketSummary {
|
|
|
37
37
|
misses: number;
|
|
38
38
|
file: string;
|
|
39
39
|
}
|
|
40
|
+
export interface FlowStepInput {
|
|
41
|
+
route: string;
|
|
42
|
+
label?: string;
|
|
43
|
+
via?: string;
|
|
44
|
+
viewport?: string;
|
|
45
|
+
note?: string;
|
|
46
|
+
spec?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface FlowBranchInput {
|
|
49
|
+
id?: string;
|
|
50
|
+
label: string;
|
|
51
|
+
from: string;
|
|
52
|
+
steps: FlowStepInput[];
|
|
53
|
+
}
|
|
54
|
+
export interface FlowBody {
|
|
55
|
+
title: string;
|
|
56
|
+
description: string;
|
|
57
|
+
intent: string;
|
|
58
|
+
acceptance: string;
|
|
59
|
+
steps: FlowStepInput[];
|
|
60
|
+
branches: FlowBranchInput[];
|
|
61
|
+
}
|
|
62
|
+
export type SaveFlowInput = FlowBody & {
|
|
63
|
+
id: string | null;
|
|
64
|
+
};
|
|
65
|
+
export interface SaveFlowResult {
|
|
66
|
+
ok: boolean;
|
|
67
|
+
flowId?: string;
|
|
68
|
+
ticketId?: string | null;
|
|
69
|
+
file?: string | null;
|
|
70
|
+
created?: boolean;
|
|
71
|
+
note?: string;
|
|
72
|
+
error?: string;
|
|
73
|
+
}
|
package/dist/screen-frame.d.ts
CHANGED
|
@@ -5,7 +5,16 @@ export type Zoom = "fit" | 0.5 | 0.75 | 1;
|
|
|
5
5
|
export declare const FRAME_CHROME = 24;
|
|
6
6
|
export declare const STEP_GUTTER = 50;
|
|
7
7
|
export declare function fitScale(available: number, naturalWidth: number, gutters: number): number;
|
|
8
|
-
export
|
|
8
|
+
export interface RowExtent {
|
|
9
|
+
natural: number;
|
|
10
|
+
gutters: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function rowExtent(widths: readonly number[]): RowExtent;
|
|
13
|
+
export declare function framedWidth(width: number, scale: number): number;
|
|
14
|
+
export declare function columnWidth(width: number, scale: number): number;
|
|
15
|
+
export declare function rowWidth(widths: readonly number[], scale: number): number;
|
|
16
|
+
export declare function fitRows(available: number, rows: readonly RowExtent[]): number;
|
|
17
|
+
export declare function useScale(zoom: Zoom, rows: readonly RowExtent[]): {
|
|
9
18
|
ref: import("react").RefObject<HTMLDivElement | null>;
|
|
10
19
|
scale: number;
|
|
11
20
|
};
|
package/dist/screen-frame.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as
|
|
1
|
+
"use client";import{jsx as o}from"react/jsx-runtime";import{useEffect as x,useRef as g,useState as b}from"react";import{FrameShell as p}from"./frame";import{PickBox as M}from"./pick-box";const S="data-workbench-scale",u=.15,l=24,d=50,E=8;function R(t,e,r){if(e<=0)return 1;const n=t-r-E;return n<=0?u:Math.min(1,Math.max(u,n/e))}function C(t){return{natural:t.reduce((e,r)=>e+r,0),gutters:t.length*l+Math.max(0,t.length-1)*d}}function s(t,e){return Math.floor(t*e)}function f(t,e){return s(t,e)+l}function F(t,e){return t.reduce((r,n)=>r+f(n,e),0)+Math.max(0,t.length-1)*d}function A(t,e){return e.reduce((r,n)=>Math.min(r,R(t,n.natural,n.gutters)),1)}function N(t,e){const r=g(null),[n,c]=b(0);x(()=>{const i=r.current;if(!i)return;const h=new ResizeObserver(m=>{c(m[0]?.contentRect.width??0)});return h.observe(i),()=>h.disconnect()},[]);const a=t==="fit"?A(n,e):t;return{ref:r,scale:a}}function $({viewport:t,scale:e,label:r,children:n,editing:c}){const a=s(t.width,e),i=s(t.height,e);return o("div",{style:{width:f(t.width,e)},children:o(p,{label:r,meta:`${t.width}\xD7${t.height} \xB7 ${Math.round(e*100)}%`,children:o("div",{className:"bg-zinc-100 p-3 dark:bg-zinc-800",children:o(M,{enabled:c,children:o("div",{[S]:String(e),className:"relative overflow-hidden",style:{width:a,height:i},children:o("div",{className:"absolute left-0 top-0",style:{width:t.width,height:t.height,transform:`scale(${e})`,transformOrigin:"top left"},children:n})})})})})})}export{l as FRAME_CHROME,S as SCALE_ATTR,d as STEP_GUTTER,$ as ScreenFrame,f as columnWidth,A as fitRows,R as fitScale,s as framedWidth,C as rowExtent,F as rowWidth,N as useScale};
|
package/dist/screen-toolbar.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as c}from"react/jsx-runtime";import{useViewerConfig as
|
|
1
|
+
"use client";import{jsx as e,jsxs as c}from"react/jsx-runtime";import{useViewerConfig as w}from"./config-context";import{cx as d}from"./cx";import{workbenchUrl as C}from"./manifest";const N="rounded-md border border-zinc-300 px-2 py-1 text-[11px] font-medium text-zinc-600 hover:bg-zinc-100 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800",j="auto";function s({options:n,value:a,onChange:o,disabled:t=!1,disabledReason:i}){return e("div",{className:d("flex rounded-md border border-zinc-300 p-0.5 dark:border-zinc-700",t&&"opacity-40"),title:t?i:void 0,children:n.map(r=>e("button",{type:"button",disabled:t,onClick:()=>o(r.id),title:t?i:r.note??void 0,className:d("rounded px-2 py-1 text-[11px] font-medium transition-colors",r.id===a?"bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900":"text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"),children:r.label},String(r.id)))})}function b({label:n,children:a}){return c("span",{className:"flex items-center gap-1.5",children:[e("span",{className:"text-[10px] font-medium uppercase tracking-wider text-zinc-400 dark:text-zinc-500",children:n}),a]})}const A=[{id:"fit",label:"Ajustar"},{id:.5,label:"50%"},{id:.75,label:"75%"},{id:1,label:"100%"}],E=[{id:"light",label:"Claro"},{id:"dark",label:"Oscuro"},{id:"split",label:"Ambos"}];function _({viewport:n,onViewport:a,zoom:o,onZoom:t,theme:i,onTheme:r,hint:m,actions:y,identity:x,backHref:u,zoomEnabled:S=!0,editing:p,onToggleEdit:z,pinCount:h,onOpenRequest:f,isolatedBase:g}){const k=w(),v=g?C(k,"",new URLSearchParams({...g,vp:n,zoom:String(o),theme:i,chrome:"off"})):null;return c("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-2 border-b border-zinc-200 bg-white px-6 py-2 dark:border-zinc-700 dark:bg-zinc-900",children:[u&&e("a",{href:u,className:"rounded-md px-2 py-1 text-[11px] font-medium text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900 dark:hover:bg-zinc-800 dark:hover:text-zinc-100",children:"\u2190 Open-Flow"}),x&&e("span",{className:"max-w-[16rem] truncate rounded bg-zinc-100 px-2 py-1 font-mono text-[11px] text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300",children:x}),e(b,{label:"Tama\xF1o",children:e(s,{value:n,onChange:a,options:[{id:j,label:"Auto"},...k.viewports.map(l=>({id:l.id,label:l.label,note:l.note}))]})}),e(b,{label:"Zoom",children:e(s,{value:o,onChange:t,options:A,disabled:!S,disabledReason:"En Auto el componente se dibuja en l\xEDnea, sin cuadro que escalar."})}),e(b,{label:"Tema",children:e(s,{value:i,onChange:r,options:E})}),y,c("span",{className:"ml-auto flex items-center gap-2",children:[z&&e("button",{type:"button",onClick:z,className:d("rounded-md px-2 py-1 text-[11px] font-medium transition-colors",p?"bg-amber-400 text-amber-950":"border border-zinc-300 text-zinc-600 hover:bg-zinc-100 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800"),title:"Se\xF1alar elementos (E)",children:p?"Editando \u25CF":"Editar"}),f&&c("button",{type:"button",onClick:f,className:N,children:["Solicitud",(h??0)>0?` (${h})`:""]}),v&&e("a",{href:v,target:"_blank",rel:"noreferrer",className:N,title:"Sin cromo, en una pesta\xF1a nueva",children:"Abrir aislado \u2197"})]}),m&&e("p",{className:"basis-full text-[11px] leading-snug text-zinc-500 dark:text-zinc-400",children:m})]})}export{j as AUTO,N as CHIP,_ as ScreenToolbar,s as SegmentedControl};
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
1
|
+
import type { NewTicketInput, SaveFlowInput, SaveFlowResult, TicketSummary } from "./pin";
|
|
2
2
|
export declare function readTickets(): Promise<TicketSummary[]>;
|
|
3
3
|
export declare function writeTicket(input: NewTicketInput): Promise<{
|
|
4
4
|
ok: boolean;
|
|
@@ -7,3 +7,4 @@ export declare function writeTicket(input: NewTicketInput): Promise<{
|
|
|
7
7
|
prompt?: string;
|
|
8
8
|
error?: string;
|
|
9
9
|
}>;
|
|
10
|
+
export declare function saveFlow(input: SaveFlowInput): Promise<SaveFlowResult>;
|
package/dist/server.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{execFile as
|
|
1
|
+
import{execFile as _}from"node:child_process";import{promisify as $}from"node:util";const m=$(_),u=120,i=4e3,A=50,h=3e4,p=16*1024*1024;function y(){return process.env.NODE_ENV==="development"}function E(){if(!y())throw new Error("El taller s\xF3lo escribe en desarrollo.")}function s(e,r){return[...(e??"").trim()].slice(0,r).join("")}function g(){return"workbench"}function F(e){return typeof e=="object"&&e!==null&&"id"in e&&"path"in e}function k(e){if(typeof e=="object"&&e!==null&&"stderr"in e){const o=String(e.stderr).trim().split(`
|
|
2
|
+
`).filter(Boolean).at(-1);if(o)return o.replace(/^(error|Error):\s*/,"")}return e instanceof Error?e.message:"Fall\xF3 la escritura."}async function P(){if(!y())return[];try{const{stdout:e}=await m(g(),["tickets"],{cwd:process.cwd(),timeout:h,maxBuffer:p}),r=JSON.parse(e);return Array.isArray(r)?r:[]}catch{return[]}}async function J(e){return E(),b(()=>I(e))}async function I(e){const r=s(e.title,u);if(r.length===0)return{ok:!1,error:"Falta el t\xEDtulo."};const o=s(e.surface,100);if(o.length===0)return{ok:!1,error:"Falta la superficie."};const f=JSON.stringify({intent:s(e.intent,i),acceptance:s(e.acceptance,i),route:s(e.route,200),pins:(e.pins??[]).slice(0,A).map(n=>({note:s(n.note,500),element:{tag:s(n.element.tag,40),classes:s(n.element.classes,300),text:s(n.element.text,120),path:s(n.element.path,300)},node:n.node})),errors:(e.errors??[]).slice(0,20).map(n=>({message:s(n.message,500),component:n.component,file:n.file,route:n.route}))});try{const n=m(g(),["ticket",o,r,"--json"],{cwd:process.cwd(),timeout:h,maxBuffer:p});n.child.stdin?.on("error",()=>{}),n.child.stdin?.end(f);const{stdout:w}=await n,d=JSON.parse(w.trim());if(!F(d))return{ok:!0};const l=String(d.id),t=String(d.path),c=`Lee ${t} y ejec\xFAtalo. Es un ticket del taller contra la superficie "${o}"; el mapa de archivos ya est\xE1 dentro. Al terminar: commit con ${l} en el mensaje, luego \`workbench validate ${l}\`.`;return{ok:!0,id:l,file:t,prompt:c}}catch(n){return{ok:!1,error:k(n)}}}const S=12,T=80;function j(e){return e.length===0||e.length>100||e.startsWith("-")?!0:[...e].some(r=>{const o=r.codePointAt(0)??0;return o<32||o===127})}const v=[["route",200],["label",u],["via",T],["viewport",40],["note",2e3],["spec",i]];function B(e){for(const[r,o]of v)if((e[r]??"").length>o)return`${r} (l\xEDmite ${o})`;return null}function M(e){return typeof e=="object"&&e!==null&&"flowId"in e}let x=Promise.resolve();function b(e){const r=x.then(e,e);return x=r.catch(()=>{}),r}async function U(e){return E(),b(()=>X(e))}async function X(e){const r=(e.title??"").trim();if(e.id===null&&r.length===0)return{ok:!1,error:"Falta el t\xEDtulo."};if(r.length>u)return{ok:!1,error:`El t\xEDtulo es demasiado largo (l\xEDmite ${u}).`};if(e.id!==null&&j(e.id))return{ok:!1,error:"El id del recorrido no es v\xE1lido."};const o=e.steps??[],f=e.branches??[];if(!o.some(t=>(t.route??"").trim().length>0))return{ok:!1,error:"Un recorrido necesita al menos un paso con ruta."};for(const t of[...o,...f.flatMap(c=>c.steps??[])]){const c=B(t);if(c)return{ok:!1,error:`Un texto del paso \xAB${(t.route??"").slice(0,60)}\xBB es demasiado largo: ${c}.`}}for(const t of f)if((t.label??"").length>u||(t.from??"").length>200||(t.id??"").length>100)return{ok:!1,error:`La rama \xAB${(t.label||t.id||"").slice(0,60)}\xBB tiene un texto demasiado largo.`};if((e.description??"").length>i||(e.intent??"").length>i||(e.acceptance??"").length>i)return{ok:!1,error:`Un texto del recorrido es demasiado largo (l\xEDmite ${i}).`};if(o.length+f.reduce((t,c)=>t+(c.steps?.length??0),0)>S)return{ok:!1,error:`un recorrido tiene como m\xE1ximo ${S} pantallas, contando las ramas`};const w=JSON.stringify({title:r,description:e.description??"",intent:e.intent??"",acceptance:e.acceptance??"",steps:o,branches:f}),d=e.id===null?["flow","new",r,"--json"]:["flow","set",e.id,"--json"];let l;try{const t=m(g(),d,{cwd:process.cwd(),timeout:h,maxBuffer:p});t.child.stdin?.on("error",()=>{}),t.child.stdin?.end(w);const{stdout:c}=await t,a=JSON.parse(c.trim());if(!M(a))return{ok:!0};l={flowId:String(a.flowId),ticketId:a.ticketId==null?null:String(a.ticketId),file:a.path==null?null:String(a.path),created:"created"in a?!!a.created:!0}}catch(t){return{ok:!1,error:k(t)}}try{return await m(g(),["scan"],{cwd:process.cwd(),timeout:h,maxBuffer:p}),{ok:!0,...l}}catch(t){return{ok:!0,...l,note:`Se escribi\xF3, pero el scan fall\xF3: ${k(t)}. Ejecuta \`workbench scan\` para ver el cambio.`}}}export{P as readTickets,U as saveFlow,J as writeTicket};
|
package/dist/workbench-app.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Manifest } from "./manifest.types";
|
|
2
|
-
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
2
|
+
import type { NewTicketInput, SaveFlowInput, SaveFlowResult, TicketSummary } from "./pin";
|
|
3
3
|
import type { RegistryEntry } from "./registry";
|
|
4
4
|
import { type CreateResult } from "./ticket-drawer";
|
|
5
5
|
export type Tab = "elementos" | "componentes" | "flujos" | "superficies";
|
|
@@ -13,10 +13,11 @@ export interface WorkbenchView {
|
|
|
13
13
|
theme?: string;
|
|
14
14
|
chrome?: string;
|
|
15
15
|
}
|
|
16
|
-
export declare function WorkbenchApp({ manifest, registry, tickets, view, onCreateTicket, }: {
|
|
16
|
+
export declare function WorkbenchApp({ manifest, registry, tickets, view, onCreateTicket, onSaveFlow, }: {
|
|
17
17
|
manifest: Manifest;
|
|
18
18
|
registry: RegistryEntry[];
|
|
19
19
|
tickets: TicketSummary[];
|
|
20
20
|
view: WorkbenchView;
|
|
21
21
|
onCreateTicket: (input: NewTicketInput) => Promise<CreateResult>;
|
|
22
|
+
onSaveFlow?: (input: SaveFlowInput) => Promise<SaveFlowResult>;
|
|
22
23
|
}): import("react").JSX.Element;
|
package/dist/workbench-app.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as n,jsxs as o,Fragment as
|
|
1
|
+
"use client";import{jsx as n,jsxs as o,Fragment as Z}from"react/jsx-runtime";import{useEffect as q,useMemo as p,useState as l}from"react";import{ManifestProvider as G}from"./config-context";import{cx as u}from"./cx";import{EditSessionOverlay as K,useEditSession as W}from"./edit-session";import{FlowStart as $}from"./flow-start";import{buildComponentIndex as J}from"./hover-inspect";import{byGroup as Q,flowById as U,groupLabel as X,tokenCount as Y}from"./manifest";import{ComponentsPanel as ee}from"./panels/components";import{ElementsPanel as te}from"./panels/elements";import{FlowsPanel as ne}from"./panels/flows";import{SurfacesPanel as oe}from"./panels/surfaces";import{TicketDrawer as re}from"./ticket-drawer";import{VerdictBadge as ie}from"./component-preview";const E=[{id:"elementos",label:"Elementos"},{id:"componentes",label:"Componentes"},{id:"flujos",label:"Flujos"},{id:"superficies",label:"Superficies"}];function ce(e){return E.find(r=>r.id===e)?.id??"componentes"}function se(e){if(e==="fit")return"fit";const r=Number(e);return r===.5||r===.75||r===1?r:void 0}function le(e){return e==="light"||e==="dark"||e==="split"?e:void 0}function Ce({manifest:e,registry:r,tickets:I,view:s,onCreateTicket:S,onSaveFlow:m}){const[i,B]=l(ce(s.tab)),[P,T]=l(s.component??e.components[0]?.id),[R,w]=l(s.flow??e.flows[0]?.id),[L,A]=l(s.surface??e.surfaces[0]?.id),[N,D]=l(""),[M,b]=l(!1),[x,f]=l(null),c=W({bareKeys:!0}),C=p(()=>e.routes.filter(t=>t.kind==="page").map(t=>t.path),[e.routes]);q(()=>{x&&e.flows.some(t=>t.id===x)&&(b(!1),f(null))},[x,e.flows]);const O=p(()=>J(e.components),[e.components]),v=s.chrome!=="off",g=e.components.find(t=>t.id===P)??e.components[0],a=U(e.flows,R),z=e.surfaces.find(t=>t.id===L)??e.surfaces[0],F={componentIndex:O,editing:c.editing,onPin:c.addPin,onHover:c.setHovering,onToggleEdit:c.toggleEditing,pinCount:c.pins.length,onOpenRequest:c.openDrawer,showChrome:v,initialViewport:s.vp,initialZoom:se(s.zoom),initialTheme:le(s.theme)},h=N.trim().toLowerCase(),j=p(()=>h?e.components.filter(t=>t.name.toLowerCase().includes(h)||t.file.toLowerCase().includes(h)):e.components,[e.components,h]),_=p(()=>Q(j),[j]),y=p(()=>({elementos:Y(e.tokens),componentes:e.components.length,flujos:e.flows.length,superficies:e.surfaces.length}),[e]),H=i==="elementos"?n(te,{}):i==="flujos"?m&&(M||!a)?n($,{routes:C,waiting:x,onSave:m,onCreated:t=>{f(t),w(t)},onCancel:a?()=>b(!1):void 0,onReset:()=>f(null)}):a?n(ne,{flow:a,...F,routes:C,onSaveFlow:m},a.id):n(k,{what:"recorridos",hint:"El rastreador no encontr\xF3 enlaces entre p\xE1ginas."}):i==="superficies"?z?n(oe,{surface:z,tickets:I}):n(k,{what:"superficies",hint:"Nada bajo el directorio de la app importa una cabecera, un rail o una barra lateral."}):g?n(ee,{entry:g,registry:r,...F}):n(k,{what:"componentes",hint:"Revisa `componentRoots` en workbench.config.json."});return o(G,{manifest:e,children:[o("div",{className:"fixed inset-0 flex bg-white text-zinc-900 dark:bg-zinc-900 dark:text-zinc-100",children:[v&&o("nav",{className:"flex w-64 shrink-0 flex-col border-r border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900",children:[o("header",{className:"border-b border-zinc-200 px-4 py-3 dark:border-zinc-700",children:[n("h1",{className:"text-sm font-semibold",title:e.config.subtitle,children:"Open-Flow"}),n("p",{className:"mt-0.5 text-[11px] leading-snug text-zinc-500 dark:text-zinc-400",children:e.config.title})]}),n("ul",{className:"border-b border-zinc-200 p-2 dark:border-zinc-700",children:E.map(t=>n("li",{children:o("button",{type:"button",onClick:()=>B(t.id),"aria-current":t.id===i?"true":void 0,className:u("flex w-full items-center justify-between rounded px-2 py-1.5 text-left text-[12px] font-medium",t.id===i?"bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900":"text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"),children:[n("span",{children:t.label}),n("span",{className:u("text-[11px] tabular-nums",t.id===i?"text-zinc-300 dark:text-zinc-600":"text-zinc-500 dark:text-zinc-400"),children:y[t.id]})]})},t.id))}),o("div",{className:"min-h-0 flex-1 overflow-auto p-2",children:[i==="componentes"&&o(Z,{children:[n("input",{value:N,onChange:t=>D(t.target.value),placeholder:`Filtrar ${e.components.length}\u2026`,className:"mb-2 w-full rounded border border-zinc-300 px-2 py-1 text-[11px] dark:border-zinc-700 dark:bg-zinc-800"}),_.map(([t,V])=>o("section",{className:"mb-3",children:[n("h2",{className:"px-1 pb-1 text-[10px] font-medium uppercase tracking-wider text-zinc-400",children:X(e.config,t)}),V.map(d=>o("button",{type:"button",onClick:()=>T(d.id),className:u("flex w-full items-center gap-1.5 rounded px-2 py-1 text-left text-[12px]",d.id===g?.id?"bg-zinc-200 font-medium dark:bg-zinc-800":"text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"),children:[n("span",{className:"truncate",children:d.name}),d.verdict!=="auto"&&n("span",{className:"ml-auto shrink-0",children:n(ie,{verdict:d.verdict})})]},d.id))]},t))]}),i==="flujos"&&m&&n("button",{type:"button",onClick:()=>{c.closeDrawer(),b(!0)},className:"block w-full rounded px-2 py-1 text-left text-[12px] text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100",children:"+ A\xF1adir recorrido"}),i==="flujos"&&e.flows.map(t=>o("button",{type:"button",onClick:()=>{w(t.id),b(!1)},className:u("block w-full truncate rounded px-2 py-1 text-left text-[12px]",t.id===a?.id?"bg-zinc-200 font-medium dark:bg-zinc-800":"text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"),children:[t.title,t.branches.length>0&&o("span",{className:"ml-1 text-[11px] text-zinc-500 dark:text-zinc-400",children:["\xB7 ",t.branches.length," ",t.branches.length===1?"rama":"ramas"]})]},t.id)),i==="superficies"&&e.surfaces.map(t=>n("button",{type:"button",onClick:()=>A(t.id),className:u("block w-full truncate rounded px-2 py-1 text-left text-[12px]",t.id===z?.id?"bg-zinc-200 font-medium dark:bg-zinc-800":"text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800"),children:t.label},t.id))]}),o("footer",{className:"border-t border-zinc-200 px-3 py-2 text-[10px] text-zinc-400 dark:border-zinc-700",children:[e.stats.filesScanned," archivos \xB7 ",e.stats.elapsedMs," ms \xB7"," ",e.generatedBy,e.stats.parseFailures.length>0&&o("span",{className:"block text-amber-600 dark:text-amber-400",children:[e.stats.parseFailures.length," archivos no se analizaron"]})]})]}),n("main",{className:"min-w-0 flex-1",children:H})]}),n(K,{session:c}),n(re,{session:c,surfaces:e.surfaces.map(t=>({id:t.id,label:t.label,weight:t.weight,predictedFileCount:t.predictedFiles.length})),onCreate:S})]})}function k({what:e,hint:r}){return n("div",{className:"flex h-full items-center justify-center p-10",children:o("p",{className:"max-w-sm text-center text-sm text-zinc-500 dark:text-zinc-400",children:["No se encontraron ",e,". ",r]})})}export{Ce as WorkbenchApp};
|
package/package.json
CHANGED