@open-flow/ui 0.2.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/LICENSE +94 -0
- package/README.md +40 -0
- package/dist/app.d.ts +10 -0
- package/dist/app.js +1 -0
- package/dist/component-preview.d.ts +25 -0
- package/dist/component-preview.js +1 -0
- package/dist/config-context.d.ts +8 -0
- package/dist/config-context.js +1 -0
- package/dist/cx.d.ts +1 -0
- package/dist/cx.js +1 -0
- package/dist/demo.d.ts +18 -0
- package/dist/demo.js +1 -0
- package/dist/dev-actions.d.ts +9 -0
- package/dist/dev-actions.js +1 -0
- package/dist/dev-actions.noop.d.ts +3 -0
- package/dist/dev-actions.noop.js +1 -0
- package/dist/dom-realm.d.ts +4 -0
- package/dist/dom-realm.js +1 -0
- package/dist/edit-mode.d.ts +7 -0
- package/dist/edit-mode.js +1 -0
- package/dist/edit-session.d.ts +23 -0
- package/dist/edit-session.js +1 -0
- package/dist/error-boundary.d.ts +17 -0
- package/dist/error-boundary.js +1 -0
- package/dist/frame-view.d.ts +11 -0
- package/dist/frame-view.js +1 -0
- package/dist/frame.d.ts +29 -0
- package/dist/frame.js +1 -0
- package/dist/hover-inspect.d.ts +17 -0
- package/dist/hover-inspect.js +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -0
- package/dist/manifest.d.ts +19 -0
- package/dist/manifest.js +1 -0
- package/dist/manifest.types.d.ts +169 -0
- package/dist/manifest.types.js +1 -0
- package/dist/mirror.d.ts +7 -0
- package/dist/mirror.js +1 -0
- package/dist/overlay.d.ts +6 -0
- package/dist/overlay.js +1 -0
- package/dist/overlay.noop.d.ts +4 -0
- package/dist/overlay.noop.js +1 -0
- package/dist/panels/components.d.ts +22 -0
- package/dist/panels/components.js +1 -0
- package/dist/panels/elements.d.ts +1 -0
- package/dist/panels/elements.js +1 -0
- package/dist/panels/flows.d.ts +20 -0
- package/dist/panels/flows.js +1 -0
- package/dist/panels/surfaces.d.ts +6 -0
- package/dist/panels/surfaces.js +1 -0
- package/dist/parse-manifest.d.ts +3 -0
- package/dist/parse-manifest.js +1 -0
- package/dist/pick-box.d.ts +7 -0
- package/dist/pick-box.js +1 -0
- package/dist/pick-highlight.d.ts +20 -0
- package/dist/pick-highlight.js +1 -0
- package/dist/pin.d.ts +39 -0
- package/dist/pin.js +0 -0
- package/dist/registry.d.ts +24 -0
- package/dist/registry.js +1 -0
- package/dist/runtime-errors.d.ts +3 -0
- package/dist/runtime-errors.js +1 -0
- package/dist/screen-frame.d.ts +18 -0
- package/dist/screen-frame.js +1 -0
- package/dist/screen-toolbar.d.ts +34 -0
- package/dist/screen-toolbar.js +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +1 -0
- package/dist/ticket-drawer.d.ts +17 -0
- package/dist/ticket-drawer.js +1 -0
- package/dist/workbench-app.d.ts +22 -0
- package/dist/workbench-app.js +1 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Elastic License 2.0 (ELv2)
|
|
2
|
+
|
|
3
|
+
Copyright © 2026 Ecorona LLC
|
|
4
|
+
|
|
5
|
+
**Acceptance**
|
|
6
|
+
|
|
7
|
+
By using the software, you agree to all of the terms and conditions below.
|
|
8
|
+
|
|
9
|
+
**Copyright License**
|
|
10
|
+
|
|
11
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide,
|
|
12
|
+
non-sublicensable, non-transferable license to use, copy, distribute, make
|
|
13
|
+
available, and prepare derivative works of the software, in each case subject
|
|
14
|
+
to the limitations and conditions below.
|
|
15
|
+
|
|
16
|
+
**Limitations**
|
|
17
|
+
|
|
18
|
+
You may not provide the software to third parties as a hosted or managed
|
|
19
|
+
service, where the service provides users with access to any substantial set
|
|
20
|
+
of the features or functionality of the software.
|
|
21
|
+
|
|
22
|
+
You may not move, change, disable, or circumvent the license key functionality
|
|
23
|
+
in the software, and you may not remove or obscure any functionality in the
|
|
24
|
+
software that is protected by the license key.
|
|
25
|
+
|
|
26
|
+
You may not alter, remove, or obscure any licensing, copyright, or other
|
|
27
|
+
notices of the licensor in the software. Any use of the licensor's trademarks
|
|
28
|
+
is subject to applicable law.
|
|
29
|
+
|
|
30
|
+
**Patents**
|
|
31
|
+
|
|
32
|
+
The licensor grants you a license, under any patent claims the licensor can
|
|
33
|
+
license, or becomes able to license, to make, have made, use, sell, offer for
|
|
34
|
+
sale, import and have imported the software, in each case subject to the
|
|
35
|
+
limitations and conditions in this license. This license does not cover any
|
|
36
|
+
patent claims that you cause to be infringed by modifications or additions to
|
|
37
|
+
the software. If you or your company make any written claim that the software
|
|
38
|
+
infringes or contributes to infringement of any patent, your patent license
|
|
39
|
+
for the software granted under these terms ends immediately. If your company
|
|
40
|
+
makes such a claim, your patent license ends immediately for work on behalf of
|
|
41
|
+
your company.
|
|
42
|
+
|
|
43
|
+
**Notices**
|
|
44
|
+
|
|
45
|
+
You must ensure that anyone who gets a copy of any part of the software from
|
|
46
|
+
you also gets a copy of these terms.
|
|
47
|
+
|
|
48
|
+
If you modify the software, you must include in any modified copies of the
|
|
49
|
+
software prominent notices stating that you have modified the software.
|
|
50
|
+
|
|
51
|
+
**No Other Rights**
|
|
52
|
+
|
|
53
|
+
These terms do not imply any licenses other than those expressly granted in
|
|
54
|
+
these terms.
|
|
55
|
+
|
|
56
|
+
**Termination**
|
|
57
|
+
|
|
58
|
+
If you use the software in violation of these terms, such use is not licensed,
|
|
59
|
+
and your licenses will automatically terminate. If the licensor provides you
|
|
60
|
+
with a notice of your violation, and you cease all violation of this license
|
|
61
|
+
no later than 30 days after you receive that notice, your licenses will be
|
|
62
|
+
reinstated retroactively. However, if you violate these terms after such
|
|
63
|
+
reinstatement, any additional violation of these terms will cause your
|
|
64
|
+
licenses to terminate automatically and permanently.
|
|
65
|
+
|
|
66
|
+
**No Liability**
|
|
67
|
+
|
|
68
|
+
*As far as the law allows, the software comes as is, without any warranty or
|
|
69
|
+
condition, and the licensor will not be liable to you for any damages arising
|
|
70
|
+
out of these terms or the use or nature of the software, under any kind of
|
|
71
|
+
legal claim.*
|
|
72
|
+
|
|
73
|
+
**Definitions**
|
|
74
|
+
|
|
75
|
+
The **licensor** is the entity offering these terms, and the **software** is
|
|
76
|
+
the software the licensor makes available under these terms, including any
|
|
77
|
+
portion of it.
|
|
78
|
+
|
|
79
|
+
**you** refers to the individual or entity agreeing to these terms.
|
|
80
|
+
|
|
81
|
+
**your company** is any legal entity, sole proprietorship, or other kind of
|
|
82
|
+
organization that you work for, plus all organizations that have control over,
|
|
83
|
+
are under the control of, or are under common control with that organization.
|
|
84
|
+
**control** means ownership of substantially all the assets of an entity, or
|
|
85
|
+
the power to direct its management and policies by vote, contract, or
|
|
86
|
+
otherwise. Control can be direct or indirect.
|
|
87
|
+
|
|
88
|
+
**your licenses** are all the licenses granted to you for the software under
|
|
89
|
+
these terms.
|
|
90
|
+
|
|
91
|
+
**use** means anything you do with the software requiring one of your
|
|
92
|
+
licenses.
|
|
93
|
+
|
|
94
|
+
**trademark** means trademarks, service marks, and similar rights.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# open-flow
|
|
2
|
+
|
|
3
|
+
Un taller vivo sobre la app Next.js que ya tienes — componentes reales, tokens
|
|
4
|
+
reales, recorridos reales. Nada es una copia: el visor importa los componentes
|
|
5
|
+
de tu propia app, así que la vista previa y el componente publicado no pueden
|
|
6
|
+
divergir, porque son el mismo código.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
pnpm add -D @open-flow/ui
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Público y sin configuración: cualquier repositorio lo instala sin tokens ni
|
|
13
|
+
registros adicionales.
|
|
14
|
+
|
|
15
|
+
## Las dos mitades
|
|
16
|
+
|
|
17
|
+
- **`@open-flow/ui`** (este repositorio, código abierto): el visor completo —
|
|
18
|
+
Elementos, Componentes, Flujos con su tablero de espejos, Superficies, el
|
|
19
|
+
overlay ⌥P para señalar sobre páginas reales, y la API de demos.
|
|
20
|
+
- **El motor de escaneo** (privado): el analizador que lee tu repositorio y
|
|
21
|
+
produce el mapa que este visor pinta. Se distribuye por separado, con
|
|
22
|
+
autorización de Ecorona LLC.
|
|
23
|
+
|
|
24
|
+
El visor funciona sobre los artefactos que el motor genera (`.workbench/`);
|
|
25
|
+
sin el motor, puedes montar el visor con artefactos ya generados.
|
|
26
|
+
|
|
27
|
+
## Desarrollo
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
pnpm install
|
|
31
|
+
pnpm build # tsc + minificado
|
|
32
|
+
pnpm test # vitest
|
|
33
|
+
pnpm typecheck
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Licencia
|
|
37
|
+
|
|
38
|
+
Elastic License 2.0 — el código es visible y modificable; no puede ofrecerse
|
|
39
|
+
como servicio gestionado a terceros ni eludirse la separación con el motor.
|
|
40
|
+
Ver [LICENSE](./LICENSE). _(Texto pendiente de revisión legal por Ecorona LLC.)_
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
2
|
+
import type { RegistryEntry } from "./registry";
|
|
3
|
+
import type { CreateResult } from "./ticket-drawer";
|
|
4
|
+
export interface WorkbenchClientProps {
|
|
5
|
+
manifest: unknown;
|
|
6
|
+
registry: RegistryEntry[];
|
|
7
|
+
onCreateTicket: (input: NewTicketInput) => Promise<CreateResult>;
|
|
8
|
+
onLoadTickets?: () => Promise<TicketSummary[]>;
|
|
9
|
+
}
|
|
10
|
+
export declare function WorkbenchClient(props: WorkbenchClientProps): import("react").JSX.Element;
|
package/dist/app.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as r}from"react/jsx-runtime";import{Suspense as p,useEffect as d,useMemo as l,useState as h}from"react";import{useSearchParams as g}from"next/navigation";import{FrameView as v}from"./frame-view";import{parseManifest as w}from"./parse-manifest";import{WorkbenchApp as b}from"./workbench-app";function V(n){return r(p,{fallback:null,children:r(x,{...n})})}function k(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}){const t=g(),[u,c]=h([]),m=l(()=>w(n),[n]);d(()=>{if(!i)return;let s=!0;return i().then(a=>{s&&c(a)}),()=>{s=!1}},[i]);const f=t.get("route")??void 0;return t.get("view")==="frame"||f?r(v,{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(b,{manifest:m,registry:e,tickets:u,view:k(t),onCreateTicket:o})}export{V as WorkbenchClient};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { ComponentEntry, Renderability } from "./manifest.types";
|
|
3
|
+
import { type RegistryEntry } from "./registry";
|
|
4
|
+
export declare function VerdictBadge({ verdict }: {
|
|
5
|
+
verdict: Renderability;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
export declare function ComponentPreview({ entry, registry, }: {
|
|
8
|
+
entry: ComponentEntry;
|
|
9
|
+
registry: RegistryEntry | undefined;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
export declare function ScenarioPreview({ entry, registry, scenario, }: {
|
|
12
|
+
entry: ComponentEntry;
|
|
13
|
+
registry: RegistryEntry | undefined;
|
|
14
|
+
scenario: string;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
16
|
+
export declare function VariantScenarios({ entry, registry, render, }: {
|
|
17
|
+
entry: ComponentEntry;
|
|
18
|
+
registry: RegistryEntry | undefined;
|
|
19
|
+
render: (name: string, description: string | undefined, node: ReactNode) => ReactNode;
|
|
20
|
+
}): import("react").JSX.Element | null;
|
|
21
|
+
export declare function ComponentScenarios({ entry, registry, render, }: {
|
|
22
|
+
entry: ComponentEntry;
|
|
23
|
+
registry: RegistryEntry | undefined;
|
|
24
|
+
render: (name: string, description: string | undefined, node: ReactNode) => ReactNode;
|
|
25
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as n,jsxs as l,Fragment as c}from"react/jsx-runtime";import{Fragment as b,Suspense as s}from"react";import{cx as g}from"./cx";import{PreviewErrorBoundary as m}from"./error-boundary";import{sampleProps as v,useComponentModule as u}from"./registry";const h={demo:{label:"demo",hint:"Escrita a mano, junto al componente.",tone:"bg-emerald-100 text-emerald-900 dark:bg-emerald-950 dark:text-emerald-200"},auto:{label:"autom\xE1tico",hint:"No necesita props: esto es el componente tal cual.",tone:"bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"},synthesized:{label:"props inventados",hint:"El taller rellen\xF3 los props obligatorios. Sirve para ver la forma, no para juzgar el contenido.",tone:"bg-amber-100 text-amber-900 dark:bg-amber-950 dark:text-amber-200"},"needs-demo":{label:"necesita demo",hint:"Sus props obligatorios no se pueden inventar \u2014 una funci\xF3n, un objeto o un tipo importado.",tone:"bg-zinc-200 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"},server:{label:"componente de servidor",hint:"No existe en el grafo del cliente. M\xEDralo en un flujo, que renderiza la p\xE1gina real.",tone:"bg-sky-100 text-sky-900 dark:bg-sky-950 dark:text-sky-200"}};function C({verdict:e}){const r=h[e];return n("span",{title:r.hint,className:g("rounded px-1.5 py-0.5 text-[10px] font-medium",r.tone),children:r.label})}function f({entry:e}){const r=h[e.verdict],a=e.props.filter(t=>t.required&&!t.sample);return l("div",{className:"rounded-lg border border-dashed border-zinc-300 p-6 text-sm dark:border-zinc-700",children:[n("p",{className:"font-medium text-zinc-700 dark:text-zinc-200",children:r.hint}),a.length>0&&l(c,{children:[n("p",{className:"mt-3 text-[11px] uppercase tracking-wider text-zinc-400",children:"Props que no se pudieron inventar"}),n("ul",{className:"mt-1 space-y-0.5 font-mono text-[11px] text-zinc-600 dark:text-zinc-400",children:a.map(t=>l("li",{children:[t.name,": ",t.typeText||"?"]},t.name))})]}),e.verdict==="needs-demo"&&l("p",{className:"mt-3 text-[11px] text-zinc-500 dark:text-zinc-400",children:["Crea ",n("code",{className:"font-mono",children:e.file.replace(/\.tsx$/,".demo.tsx")})," y el taller lo usar\xE1 en lugar de esto."]})]})}function p({entry:e,registry:r,overrides:a}){const t=u(r);if(t.error)return n("p",{className:"rounded-lg border border-red-300 bg-red-50 p-4 text-sm text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200",children:t.error});if(t.demo)return n(c,{children:t.demo.render()});const{Component:o}=t;if(!o)return n(f,{entry:e});const{props:d,children:i}=v(e.props);return n(o,{...d,...a,children:i})}function P({entry:e,registry:r}){return!r||e.verdict==="server"||e.verdict==="needs-demo"?n(f,{entry:e}):n(m,{label:e.file,component:e.name,children:n(s,{fallback:n(x,{}),children:n(p,{entry:e,registry:r})})})}function E({entry:e,registry:r,scenario:a}){return!r||e.verdict==="server"||e.verdict==="needs-demo"?n(f,{entry:e}):n(m,{label:`${e.file} \xB7 ${a}`,component:e.name,children:n(s,{fallback:n(x,{}),children:n(k,{entry:e,registry:r,scenario:a})})})}function k({entry:e,registry:r,scenario:a}){const o=u(r).demo?.scenarios?.find(i=>i.name===a);if(o)return n(c,{children:o.render()});const d=e.variants.find(i=>i.name===a);return d?n("div",{className:"flex flex-wrap items-start gap-4",children:d.values.map(i=>l("figure",{className:"flex flex-col items-start gap-1",children:[n(p,{entry:e,registry:r,overrides:{[d.name]:i}}),l("figcaption",{className:"font-mono text-[10px] text-zinc-500 dark:text-zinc-400",children:[i,i===d.default&&" \xB7"]})]},i))}):n(p,{entry:e,registry:r})}function q({entry:e,registry:r,render:a}){return!r||r.demo||e.variants.length===0||e.verdict==="server"||e.verdict==="needs-demo"?null:n(c,{children:e.variants.map(t=>n(b,{children:a(t.name,t.default?`${t.values.length} valores \xB7 por defecto ${t.default}`:`${t.values.length} valores`,n("div",{className:"flex flex-wrap items-start gap-4",children:t.values.map(o=>l("figure",{className:"flex flex-col items-start gap-1",children:[n(m,{label:e.file,component:e.name,children:n(s,{fallback:n(x,{}),children:n(p,{entry:e,registry:r,overrides:{[t.name]:o}})})}),l("figcaption",{className:"font-mono text-[10px] text-zinc-500 dark:text-zinc-400",children:[o,o===t.default&&" \xB7"]})]},o))}))},t.name))})}function F({entry:e,registry:r,render:a}){return r?.demo?n(s,{fallback:null,children:n(z,{entry:e,registry:r,render:a})}):null}function z({entry:e,registry:r,render:a}){const o=u(r).demo?.scenarios??[];return o.length===0?null:n(c,{children:o.map(d=>n(m,{label:`${e.file} \xB7 ${d.name}`,component:e.name,children:a(d.name,d.description,d.render())},d.name))})}function x(){return n("div",{className:"h-24 animate-pulse rounded-lg bg-zinc-100 dark:bg-zinc-800","aria-hidden":!0})}export{P as ComponentPreview,F as ComponentScenarios,E as ScenarioPreview,q as VariantScenarios,C as VerdictBadge};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Manifest, ViewerConfig } from "./manifest.types";
|
|
3
|
+
export declare function ManifestProvider({ manifest, children, }: {
|
|
4
|
+
manifest: Manifest;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
export declare function useManifest(): Manifest;
|
|
8
|
+
export declare function useViewerConfig(): ViewerConfig;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as r}from"react/jsx-runtime";import{createContext as o,useContext as i}from"react";const t=o(null);function a({manifest:e,children:n}){return r(t.Provider,{value:e,children:n})}function s(){const e=i(t);if(!e)throw new Error("Falta <ManifestProvider>: el visor necesita un manifiesto.");return e}function c(){return s().config}export{a as ManifestProvider,s as useManifest,c as useViewerConfig};
|
package/dist/cx.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cx(...parts: Array<string | false | null | undefined>): string;
|
package/dist/cx.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function o(...n){return n.filter(Boolean).join(" ")}export{o as cx};
|
package/dist/demo.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface Scenario {
|
|
3
|
+
name: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
render: () => ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export interface Demo {
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
render: () => ReactNode;
|
|
11
|
+
scenarios?: Scenario[];
|
|
12
|
+
preferDark?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface DemoModule {
|
|
15
|
+
default: Demo;
|
|
16
|
+
}
|
|
17
|
+
export declare function defineDemo(demo: Demo): Demo;
|
|
18
|
+
export declare function scenario(name: string, render: () => ReactNode, description?: string): Scenario;
|
package/dist/demo.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function o(e){return e}function t(e,n,r){return{name:e,render:n,description:r}}export{o as defineDemo,t as scenario};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NewTicketInput, TicketSummary } from "./pin";
|
|
2
|
+
export declare function createTicket(input: NewTicketInput): Promise<{
|
|
3
|
+
ok: boolean;
|
|
4
|
+
id?: string;
|
|
5
|
+
file?: string;
|
|
6
|
+
prompt?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function loadTickets(): Promise<TicketSummary[]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use server";import{readTickets as r,writeTicket as t}from"./server";async function i(e){return t(e)}async function n(){return r()}export{i as createTicket,n as loadTickets};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e="El taller s\xF3lo escribe tickets en desarrollo.";async function r(t){throw new Error(e)}async function n(){return[]}export{r as createTicket,n as loadTickets};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function isElement(value: unknown): value is Element;
|
|
2
|
+
export declare function readProp(value: unknown, key: string): unknown;
|
|
3
|
+
export declare function setStyle(element: Element, property: string, value: string): void;
|
|
4
|
+
export declare function readStyle(element: Element, property: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function y(t){return typeof t!="object"||t===null?!1:Reflect.get(t,"nodeType")===1}function o(t,e){if(!(t===null||typeof t!="object"&&typeof t!="function"))try{return Reflect.get(t,e)}catch{return}}function c(t){const e=o(t,"style");return!e||typeof e!="object"||!("setProperty"in e)?null:e}function i(t,e,n){const r=c(t);if(!r)return;const f=o(r,"setProperty");typeof f=="function"&&Reflect.apply(f,r,[e,n])}function u(t,e){const n=c(t);return n===null?"":String(o(n,e)??"")}export{y as isElement,o as readProp,u as readStyle,i as setStyle};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ComponentIndex } from "./hover-inspect";
|
|
2
|
+
import { type PickTarget } from "./pick-highlight";
|
|
3
|
+
import type { Pin } from "./pin";
|
|
4
|
+
export declare function useInspect(enabled: boolean, getRoot: () => HTMLElement | null, index: ComponentIndex, callbacks: {
|
|
5
|
+
onPin: (pin: Pick<Pin, "element" | "node">) => void;
|
|
6
|
+
onHover: (target: PickTarget | null) => void;
|
|
7
|
+
}, resetKey?: string | number): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{useEffect as L,useRef as P}from"react";import{isElement as C,readProp as T}from"./dom-realm";import{lightSiblings as H,resolveNode as A}from"./hover-inspect";import{mapRect as O}from"./pick-highlight";import{BOX_ATTR as S}from"./pick-box";import{reportRuntimeError as X}from"./runtime-errors";const $=80;function j(n,i){return i||n.closest(`[${S}]`)!==null}function b(n){const i=typeof n.className=="string"?n.className:"",a=[];let r=n;for(let m=0;m<4&&r&&r.tagName!=="BODY";m++){const c=typeof r.className=="string"?r.className.split(/\s+/)[0]??"":"";a.unshift(c?`${r.tagName.toLowerCase()}.${c}`:r.tagName.toLowerCase()),r=r.parentElement}return{tag:n.tagName.toLowerCase(),classes:i.trim().split(/\s+/).slice(0,8).join(" "),text:(n.textContent??"").trim().replace(/\s+/g," ").slice(0,$),path:a.join(" > ")}}function k(n){return n.component?{component:n.component,file:n.file,surface:n.surface}:null}function Y(n,i,a,r,m=0){const c=P(r);L(()=>{c.current=r},[r]);const f=P(a);L(()=>{f.current=a},[a]),L(()=>{if(!n)return;const v=i();if(!v)return;let g=null,h=null;const p=()=>{g?.(),g=null,h=null},D=(e,o)=>{const t=e.target;if(!C(t)||!j(t,o))return;e.preventDefault(),e.stopPropagation();const s=A(t,f.current);c.current.onPin({element:b(t),node:k(s)})},R=(e,o)=>{const t=e.target;if(!C(t))return;if(!j(t,o!==null)){c.current.onHover(null),p();return}const s=A(t,f.current);c.current.onHover({rect:O(t,o),node:s}),s.component!==h&&(p(),s.component&&(h=s.component,g=H(t.ownerDocument,s.component,f.current)))},y=()=>{c.current.onHover(null),p()},l=[],N=(e,o,t)=>{const s=u=>R(u,t),w=u=>D(u,t!==null);if(e.addEventListener("click",w,!0),e.addEventListener("mouseover",s,!0),e.addEventListener("mouseleave",y,!0),l.push(()=>{e.removeEventListener("click",w,!0),e.removeEventListener("mouseover",s,!0),e.removeEventListener("mouseleave",y,!0)}),o!==null){const u=x=>{const B=String(T(x,"message")??"Promesa rechazada sin capturar");X({message:B,route:o,component:null,file:null})},E=T(e,"defaultView"),d=(E&&typeof E.addEventListener=="function"?E:null)??e;d.addEventListener("error",u,!0),d.addEventListener("unhandledrejection",u,!0),l.push(()=>{d.removeEventListener("error",u,!0),d.removeEventListener("unhandledrejection",u,!0)})}};N(v,null,null);for(const e of Array.from(v.querySelectorAll("iframe"))){const o=()=>{try{const t=e.contentDocument;if(!t)return;N(t,e.getAttribute("src"),e),t.body?.style.setProperty("cursor","crosshair"),l.push(()=>t.body?.style.removeProperty("cursor"))}catch{}};o(),e.addEventListener("load",o),l.push(()=>e.removeEventListener("load",o))}return()=>{p();for(const e of l)e()}},[n,i,m])}export{Y as useInspect};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type PickTarget } from "./pick-highlight";
|
|
2
|
+
import type { Pin, RuntimeError } from "./pin";
|
|
3
|
+
export interface EditSession {
|
|
4
|
+
editing: boolean;
|
|
5
|
+
toggleEditing: () => void;
|
|
6
|
+
pins: Pin[];
|
|
7
|
+
addPin: (pin: Pick<Pin, "element" | "node">) => void;
|
|
8
|
+
updatePin: (index: number, note: string) => void;
|
|
9
|
+
removePin: (index: number) => void;
|
|
10
|
+
clearPins: () => void;
|
|
11
|
+
hovering: PickTarget | null;
|
|
12
|
+
setHovering: (target: PickTarget | null) => void;
|
|
13
|
+
errors: RuntimeError[];
|
|
14
|
+
drawerOpen: boolean;
|
|
15
|
+
openDrawer: () => void;
|
|
16
|
+
closeDrawer: () => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function useEditSession(options?: {
|
|
19
|
+
bareKeys?: boolean;
|
|
20
|
+
}): EditSession;
|
|
21
|
+
export declare function EditSessionOverlay({ session }: {
|
|
22
|
+
session: EditSession;
|
|
23
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as S}from"react/jsx-runtime";import{useCallback as r,useEffect as g,useState as s}from"react";import{isElement as h,readProp as p}from"./dom-realm";import{PickHighlight as x}from"./pick-highlight";import{subscribeRuntimeErrors as T}from"./runtime-errors";function O(o){const u=o?.bareKeys??!1,[E,d]=s(!1),[m,a]=s([]),[y,f]=s(null),[w,l]=s(!1),[k,P]=s([]);g(()=>T(P),[]);const b=r(t=>{a(e=>[...e,{...t,note:""}]),l(!0)},[]),c=r(()=>{d(t=>(t&&f(null),!t))},[]);return g(()=>{const t=e=>{const n=e.target;h(n)&&(p(n,"isContentEditable")===!0||["INPUT","TEXTAREA","SELECT"].includes(String(p(n,"tagName"))))||(u&&(e.key==="e"||e.key==="E")&&(e.preventDefault(),c()),e.key==="Escape"&&(d(!1),f(null)),u&&(e.key==="n"||e.key==="N")&&(e.preventDefault(),l(!0)))};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[c,u]),{editing:E,toggleEditing:c,pins:m,addPin:b,updatePin:r((t,e)=>{a(n=>n.map((i,D)=>D===t?{...i,note:e}:i))},[]),removePin:r(t=>{a(e=>e.filter((n,i)=>i!==t))},[]),clearPins:r(()=>a([]),[]),hovering:y,setHovering:f,errors:k,drawerOpen:w,openDrawer:r(()=>l(!0),[]),closeDrawer:r(()=>l(!1),[])}}function j({session:o}){return o.editing?S(x,{target:o.hovering}):null}export{j as EditSessionOverlay,O as useEditSession};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Component, type ErrorInfo, type ReactNode } from "react";
|
|
2
|
+
interface Props {
|
|
3
|
+
label: string;
|
|
4
|
+
component?: string;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
interface State {
|
|
8
|
+
error: Error | null;
|
|
9
|
+
}
|
|
10
|
+
export declare class PreviewErrorBoundary extends Component<Props, State> {
|
|
11
|
+
state: State;
|
|
12
|
+
static getDerivedStateFromError(error: Error): State;
|
|
13
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
14
|
+
componentDidUpdate(previous: Props): void;
|
|
15
|
+
render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as r,jsxs as o}from"react/jsx-runtime";import{Component as s}from"react";import{reportRuntimeError as a}from"./runtime-errors";class i extends s{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){console.error(`[workbench] el componente lanz\xF3: ${this.props.label}`,e,t),a({message:e.message,component:this.props.component??null,file:this.props.label,route:null})}componentDidUpdate(e){e.label!==this.props.label&&this.state.error&&this.setState({error:null})}render(){const{error:e}=this.state;return e?o("div",{className:"m-4 rounded-lg border border-red-300 bg-red-50 p-4 text-sm dark:border-red-800 dark:bg-red-950",children:[r("p",{className:"font-semibold text-red-800 dark:text-red-200",children:"Este componente lanz\xF3 un error"}),r("p",{className:"mt-1 font-mono text-[11px] text-red-700 dark:text-red-300",children:this.props.label}),r("pre",{className:"mt-3 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-red-900 dark:text-red-200",children:e.message}),r("p",{className:"mt-3 text-[11px] text-red-700 dark:text-red-300",children:"Si el taller invent\xF3 los props, es probable que falte una demo \u2014 el panel lo dice. Arregla el archivo y vuelve a seleccionarlo; no hace falta recargar."})]}):this.props.children}}export{i as PreviewErrorBoundary};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Manifest } from "./manifest.types";
|
|
2
|
+
import { type RegistryEntry } from "./registry";
|
|
3
|
+
export declare function FrameView({ manifest, registry, componentId, route, viewport: initialViewport, theme: initialTheme, scenario, }: {
|
|
4
|
+
manifest: Manifest;
|
|
5
|
+
registry: RegistryEntry[];
|
|
6
|
+
componentId?: string;
|
|
7
|
+
route?: string;
|
|
8
|
+
viewport?: string;
|
|
9
|
+
theme?: string;
|
|
10
|
+
scenario?: string;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{useCallback as M,useMemo as j,useRef as H,useState as p}from"react";import{ComponentPreview as I,ScenarioPreview as O}from"./component-preview";import{ManifestProvider as V}from"./config-context";import{useInspect as _}from"./edit-mode";import{EditSessionOverlay as A,useEditSession as B}from"./edit-session";import{InlineSurface as x,RouteFrame as T}from"./frame";import{buildComponentIndex as U}from"./hover-inspect";import{viewportById as Z,workbenchUrl as q}from"./manifest";import{PickBox as K}from"./pick-box";import{indexRegistry as k}from"./registry";import{ScreenFrame as y,useScale as D,FRAME_CHROME as G}from"./screen-frame";import{AUTO as N,ScreenToolbar as J}from"./screen-toolbar";function le({manifest:r,registry:f,componentId:h,route:n,viewport:S,theme:c,scenario:s}){const g=r.config,[d,E]=p(S??N),[m,R]=p("fit"),[u,P]=p(c==="dark"||c==="split"?c:"light"),i=B({bareKeys:!0}),w=H(null),$=j(()=>U(r.components),[r.components]),o=r.components.find(F=>F.id===h),t=d===N?null:Z(g,d),{ref:z,scale:v}=D(m,t?.width??0,G),l=u==="dark"?"dark":"light";_(i.editing,M(()=>w.current,[]),$,{onPin:i.addPin,onHover:i.setHovering},`${h??n}:${d}:${m}:${l}`);const b=o?s?e(O,{entry:o,registry:k(f).get(o.id),scenario:s}):e(I,{entry:o,registry:k(f).get(o.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="}),"."]}),C=n?t?e(y,{viewport:t,scale:v,label:n,editing:i.editing,children:e(T,{src:n,title:n,width:t.width,height:t.height})}):e(K,{enabled:i.editing,className:"h-full",children:e("iframe",{src:n,title:n,className:"h-full w-full border-0"})}):t?e(y,{viewport:t,scale:v,label:o?.name,editing:i.editing,children:e(x,{theme:l,editing:!1,children:b})}):e(x,{theme:l,editing:i.editing,children:b});return a(V,{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:R,theme:u,onTheme:P,zoomEnabled:t!==null,identity:n??(s?`${o?.name} \xB7 ${s}`:o?.name),backHref:q(g,""),editing:i.editing,onToggleEdit:i.toggleEditing,pinCount:i.pins.length}),e("div",{ref:z,className:"min-h-0 flex-1 overflow-auto",children:e("div",{ref:w,className:"h-full p-4",children:C})})]})}),e(A,{session:i})]})}export{le as FrameView};
|
package/dist/frame.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export declare function FrameShell({ label, meta, children, className, }: {
|
|
3
|
+
label?: ReactNode;
|
|
4
|
+
meta?: ReactNode;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
export declare function InlineSurface({ theme, children, padded, editing, }: {
|
|
9
|
+
theme: "light" | "dark";
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
padded?: boolean;
|
|
12
|
+
editing?: boolean;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
export declare function RouteFrame({ src, title, width, height, theme, frameRef, onLoad, }: {
|
|
15
|
+
src: string;
|
|
16
|
+
title: string;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
theme?: "light" | "dark";
|
|
20
|
+
frameRef?: (frame: HTMLIFrameElement | null) => void;
|
|
21
|
+
onLoad?: (frame: HTMLIFrameElement) => void;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
export declare function MirrorFrame({ srcdoc, title, width, height, theme, }: {
|
|
24
|
+
srcdoc: string;
|
|
25
|
+
title: string;
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
theme: "light" | "dark";
|
|
29
|
+
}): import("react").JSX.Element;
|
package/dist/frame.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as s,jsxs as x}from"react/jsx-runtime";import{useEffect as b,useRef as p}from"react";import{cx as f}from"./cx";import{isElement as g}from"./dom-realm";import{PickBox as k}from"./pick-box";function L({label:t,meta:n,children:o,className:c}){return x("div",{className:f("overflow-hidden rounded-lg border border-zinc-300 bg-white shadow-sm","dark:border-zinc-700 dark:bg-zinc-900",c),children:[(t||n)&&x("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:[s("span",{className:"truncate",children:t}),n&&s("span",{className:"truncate font-mono text-[10px] text-zinc-500 dark:text-zinc-400",children:n})]}),o]})}function y({theme:t,children:n,padded:o=!0,editing:c}){return s("div",{className:f(t==="dark"&&"dark"),children:s(k,{enabled:c,className:f("bg-background text-foreground",o&&"p-6"),children:n})})}function N({src:t,title:n,width:o,height:c,theme:i,frameRef:l,onLoad:a}){const d=p(null);return b(()=>{if(i===void 0)return;const e=d.current;if(!e)return;const r=()=>{try{e.contentDocument?.documentElement.classList.toggle("dark",i==="dark")}catch{}};r(),e.addEventListener("load",r);const u=[300,1200,2500].map(m=>setTimeout(r,m));return()=>{e.removeEventListener("load",r);for(const m of u)clearTimeout(m)}},[i,t]),s("iframe",{ref:e=>{d.current=e,l?.(e)},src:t,title:n,width:o,height:c,onLoad:e=>a?.(e.currentTarget),className:"border-0 bg-white",style:{width:o,height:c}})}function j({srcdoc:t,title:n,width:o,height:c,theme:i}){const l=p(null);return b(()=>{const a=l.current;if(!a)return;const d=r=>{const u=r.target;g(u)&&u.closest("a[href]")&&r.preventDefault()},e=()=>{try{const r=a.contentDocument;if(!r)return;r.documentElement.classList.toggle("dark",i==="dark"),r.addEventListener("click",d,!0)}catch{}};return e(),a.addEventListener("load",e),()=>{a.removeEventListener("load",e);try{a.contentDocument?.removeEventListener("click",d,!0)}catch{}}},[i,t]),s("iframe",{ref:l,srcDoc:t,title:n,sandbox:"allow-same-origin","data-workbench-mirror":"",tabIndex:-1,width:o,height:c,className:"border-0 bg-white",style:{width:o,height:c}})}export{L as FrameShell,y as InlineSurface,j as MirrorFrame,N as RouteFrame};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface IndexedComponent {
|
|
2
|
+
name: string;
|
|
3
|
+
file: string;
|
|
4
|
+
surface: string | null;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolvedNode {
|
|
7
|
+
tag: string;
|
|
8
|
+
component: string | null;
|
|
9
|
+
file: string | null;
|
|
10
|
+
candidates: IndexedComponent[];
|
|
11
|
+
surface: string | null;
|
|
12
|
+
}
|
|
13
|
+
export type ComponentIndex = Map<string, IndexedComponent[]>;
|
|
14
|
+
export declare function buildComponentIndex(components: readonly IndexedComponent[]): ComponentIndex;
|
|
15
|
+
export declare function componentNameOf(element: Element, index: ComponentIndex, maxDepth?: number): string | null;
|
|
16
|
+
export declare function resolveNode(element: Element, index: ComponentIndex): ResolvedNode;
|
|
17
|
+
export declare function lightSiblings(root: Document | Element, component: string, index: ComponentIndex): () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{isElement as g,readProp as i,readStyle as a,setStyle as u}from"./dom-realm";const h="__reactFiber$";function I(n){const e=new Map;for(const t of n){const o=e.get(t.name);o?o.push(t):e.set(t.name,[t])}return e}function y(n){for(const e of Object.keys(n))if(e.startsWith(h))return i(n,e);return null}function p(n){if(typeof n=="function"){const e=i(n,"displayName");if(typeof e=="string"&&e.length>0)return e;const t=i(n,"name");return typeof t=="string"&&t.length>0?t:null}if(typeof n=="object"&&n!==null){const e=i(n,"displayName");return typeof e=="string"&&e.length>0?e:p(i(n,"render")??i(n,"type"))}return null}function m(n,e,t=24){let o=y(n);for(let r=0;r<t&&o;r++){const f=p(i(o,"type"));if(f&&e.has(f))return f;o=i(o,"return")}return null}function N(n,e){const t=m(n,e),o=t?e.get(t)??[]:[],r=o.length===1?o[0]:void 0;return{tag:n.tagName.toLowerCase(),component:t,file:r?.file??null,candidates:o,surface:r?.surface??null}}const b="2px solid rgb(251 191 36)",c=600;function O(n,e,t){const o=[],r=n.querySelectorAll("*"),f=Math.min(r.length,c);for(let s=0;s<f;s++){const l=r[s];g(l)&&m(l,t,6)===e&&(o.push({element:l,outline:a(l,"outline"),offset:a(l,"outlineOffset")}),u(l,"outline",b),u(l,"outline-offset","1px"))}return r.length>c&&console.info(`[workbench] ${r.length} elementos en el documento; s\xF3lo se revisaron los primeros ${c} para resaltar ${e}.`),()=>{for(const{element:s,outline:l,offset:d}of o)u(s,"outline",l),u(s,"outline-offset",d)}}export{I as buildComponentIndex,m as componentNameOf,O as lightSiblings,N as resolveNode};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +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";
|
|
3
|
+
export { parseManifest } from "./parse-manifest";
|
|
4
|
+
export type { RegistryEntry } from "./registry";
|
|
5
|
+
export type { NewTicketInput, Pin, RuntimeError, TicketSummary } from "./pin";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{byGroup as e,flowById as f,frameUrl as a,groupLabel as p,surfaceForRoute as s,surfaceFromPins as t,viewportById as u,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,s as surfaceForRoute,t as surfaceFromPins,u as viewportById,l as workbenchUrl};
|
|
@@ -0,0 +1,19 @@
|
|
|
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";
|
|
3
|
+
export { MANIFEST_VERSION } from "./manifest.types";
|
|
4
|
+
export declare function groupLabel(config: ViewerConfig, group: string): string;
|
|
5
|
+
export declare function viewportById(config: ViewerConfig, id: string | undefined): Viewport;
|
|
6
|
+
export declare function workbenchUrl(config: ViewerConfig, segment: string, params?: URLSearchParams): string;
|
|
7
|
+
export declare function byGroup(components: ComponentEntry[]): Array<[string, ComponentEntry[]]>;
|
|
8
|
+
export declare function surfaceFromPins(pins: Array<{
|
|
9
|
+
node: {
|
|
10
|
+
surface: string | null;
|
|
11
|
+
} | null;
|
|
12
|
+
}>, fallback: string): string;
|
|
13
|
+
export declare function surfaceForRoute(routes: ReadonlyArray<{
|
|
14
|
+
path: string;
|
|
15
|
+
surface: string | null;
|
|
16
|
+
dynamic: boolean;
|
|
17
|
+
}>, pathname: string): string | null;
|
|
18
|
+
export declare function frameUrl(config: ViewerConfig, params: Record<string, string>): string;
|
|
19
|
+
export declare function flowById(flows: Flow[], id: string | undefined): Flow | undefined;
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{MANIFEST_VERSION as h}from"./manifest.types";function s(e,t){return e.groupLabels[t]??t}function u(e,t){const r=e.viewports.find(n=>n.id===t),o=e.viewports[0];if(r)return r;if(o)return o;throw new Error("El manifiesto no declara ning\xFAn viewport.")}function f(e,t,r){const o=e.mountPath.replace(/\/+$/,""),n=t?`${o}/${t}`:o;return r?`${n}?${r.toString()}`:n}function c(e){const t=new Map;for(const r of e){const o=t.get(r.group);o?o.push(r):t.set(r.group,[r])}return[...t.entries()]}function p(e,t){const r=new Map;for(const n of e){const i=n.node?.surface;i&&r.set(i,(r.get(i)??0)+1)}let o=null;for(const[n,i]of r)(o===null||i>(r.get(o)??0))&&(o=n);return o??t}function a(e,t){const r=e.find(n=>n.path===t);return r?r.surface:e.filter(n=>n.dynamic).map(n=>({route:n,stem:n.path.split(/[:*]/)[0]??""})).filter(({stem:n})=>n.length>1&&t.startsWith(n)).sort((n,i)=>i.stem.length-n.stem.length)[0]?.route.surface??null}function l(e,t){return f(e,"",new URLSearchParams({view:"frame",...t}))}function d(e,t){return e.find(r=>r.id===t)??e[0]}export{h as MANIFEST_VERSION,c as byGroup,d as flowById,l as frameUrl,s as groupLabel,a as surfaceForRoute,p as surfaceFromPins,u as viewportById,f as workbenchUrl};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
export type Viewport = {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
note: string | null;
|
|
7
|
+
};
|
|
8
|
+
export type ViewerConfig = {
|
|
9
|
+
title: string;
|
|
10
|
+
subtitle: string;
|
|
11
|
+
mountPath: string;
|
|
12
|
+
groupLabels: {
|
|
13
|
+
[key in string]: string;
|
|
14
|
+
};
|
|
15
|
+
viewports: Array<Viewport>;
|
|
16
|
+
};
|
|
17
|
+
export type TokenKind = "color" | "value";
|
|
18
|
+
export type Token = {
|
|
19
|
+
name: string;
|
|
20
|
+
light: string | null;
|
|
21
|
+
dark: string | null;
|
|
22
|
+
note: string | null;
|
|
23
|
+
kind: TokenKind;
|
|
24
|
+
};
|
|
25
|
+
export type TokenGroup = {
|
|
26
|
+
id: string;
|
|
27
|
+
label: string;
|
|
28
|
+
tokens: Array<Token>;
|
|
29
|
+
};
|
|
30
|
+
export type Renderability = "auto" | "synthesized" | "needs-demo" | "server" | "demo";
|
|
31
|
+
export type SampleKind = "string" | "number" | "boolean" | "node" | "enum" | "callback" | "list";
|
|
32
|
+
export type SampleValue = string | number | boolean | Array<SampleValue> | null;
|
|
33
|
+
export type PropSample = {
|
|
34
|
+
kind: SampleKind;
|
|
35
|
+
value: SampleValue;
|
|
36
|
+
};
|
|
37
|
+
export type PropSpec = {
|
|
38
|
+
name: string;
|
|
39
|
+
typeText: string;
|
|
40
|
+
required: boolean;
|
|
41
|
+
sample: PropSample | null;
|
|
42
|
+
};
|
|
43
|
+
export type VariantGroup = {
|
|
44
|
+
name: string;
|
|
45
|
+
values: Array<string>;
|
|
46
|
+
default: string | null;
|
|
47
|
+
};
|
|
48
|
+
export type ComponentEntry = {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
group: string;
|
|
52
|
+
file: string;
|
|
53
|
+
importPath: string;
|
|
54
|
+
exportName: string | null;
|
|
55
|
+
verdict: Renderability;
|
|
56
|
+
props: Array<PropSpec>;
|
|
57
|
+
variants: Array<VariantGroup>;
|
|
58
|
+
demoFile: string | null;
|
|
59
|
+
surface: string | null;
|
|
60
|
+
};
|
|
61
|
+
export type RouteKind = "page" | "handler";
|
|
62
|
+
export type RouteEntry = {
|
|
63
|
+
path: string;
|
|
64
|
+
file: string;
|
|
65
|
+
group: string | null;
|
|
66
|
+
kind: RouteKind;
|
|
67
|
+
dynamic: boolean;
|
|
68
|
+
surface: string | null;
|
|
69
|
+
};
|
|
70
|
+
export type Origin = "config" | "spider";
|
|
71
|
+
export type FlowStep = {
|
|
72
|
+
label: string;
|
|
73
|
+
route: string;
|
|
74
|
+
viewport: string;
|
|
75
|
+
note: string | null;
|
|
76
|
+
spec: string | null;
|
|
77
|
+
exists: boolean;
|
|
78
|
+
};
|
|
79
|
+
export type Flow = {
|
|
80
|
+
id: string;
|
|
81
|
+
title: string;
|
|
82
|
+
description: string | null;
|
|
83
|
+
origin: Origin;
|
|
84
|
+
steps: Array<FlowStep>;
|
|
85
|
+
};
|
|
86
|
+
export type LearnedFile = {
|
|
87
|
+
file: string;
|
|
88
|
+
ticket: string | null;
|
|
89
|
+
};
|
|
90
|
+
export type SurfaceFiles = {
|
|
91
|
+
anchors: Array<string>;
|
|
92
|
+
members: Array<string>;
|
|
93
|
+
mounts: Array<string>;
|
|
94
|
+
learned: Array<LearnedFile>;
|
|
95
|
+
};
|
|
96
|
+
export type TokenUse = {
|
|
97
|
+
token: string;
|
|
98
|
+
uses: number;
|
|
99
|
+
};
|
|
100
|
+
export type HardcodedColor = {
|
|
101
|
+
file: string;
|
|
102
|
+
values: Array<string>;
|
|
103
|
+
};
|
|
104
|
+
export type Weight = "quick" | "full";
|
|
105
|
+
export type Surface = {
|
|
106
|
+
id: string;
|
|
107
|
+
label: string;
|
|
108
|
+
description: string;
|
|
109
|
+
origin: Origin;
|
|
110
|
+
main: string | null;
|
|
111
|
+
files: SurfaceFiles;
|
|
112
|
+
shared: Array<string>;
|
|
113
|
+
logic: Array<string>;
|
|
114
|
+
routes: Array<string>;
|
|
115
|
+
absent: Array<string>;
|
|
116
|
+
tokens: Array<TokenUse>;
|
|
117
|
+
hardcodedColors: Array<HardcodedColor>;
|
|
118
|
+
components: Array<string>;
|
|
119
|
+
gotchas: Array<string>;
|
|
120
|
+
predictedFiles: Array<string>;
|
|
121
|
+
weight: Weight;
|
|
122
|
+
};
|
|
123
|
+
export type ParseFailure = {
|
|
124
|
+
file: string;
|
|
125
|
+
message: string;
|
|
126
|
+
};
|
|
127
|
+
export type ScanStats = {
|
|
128
|
+
filesScanned: number;
|
|
129
|
+
elapsedMs: bigint;
|
|
130
|
+
parseFailures: Array<ParseFailure>;
|
|
131
|
+
untraceableHrefs: number;
|
|
132
|
+
missingStylesheet: string | null;
|
|
133
|
+
droppedFlows: number;
|
|
134
|
+
};
|
|
135
|
+
export type Manifest = {
|
|
136
|
+
version: number;
|
|
137
|
+
generatedBy: string;
|
|
138
|
+
config: ViewerConfig;
|
|
139
|
+
tokens: Array<TokenGroup>;
|
|
140
|
+
components: Array<ComponentEntry>;
|
|
141
|
+
routes: Array<RouteEntry>;
|
|
142
|
+
flows: Array<Flow>;
|
|
143
|
+
surfaces: Array<Surface>;
|
|
144
|
+
stats: ScanStats;
|
|
145
|
+
};
|
|
146
|
+
export type OverlayComponent = {
|
|
147
|
+
name: string;
|
|
148
|
+
file: string;
|
|
149
|
+
surface: string | null;
|
|
150
|
+
};
|
|
151
|
+
export type OverlayRoute = {
|
|
152
|
+
path: string;
|
|
153
|
+
surface: string | null;
|
|
154
|
+
dynamic: boolean;
|
|
155
|
+
};
|
|
156
|
+
export type OverlaySurface = {
|
|
157
|
+
id: string;
|
|
158
|
+
label: string;
|
|
159
|
+
weight: Weight;
|
|
160
|
+
predictedFileCount: number;
|
|
161
|
+
};
|
|
162
|
+
export type OverlayManifest = {
|
|
163
|
+
version: number;
|
|
164
|
+
config: ViewerConfig;
|
|
165
|
+
components: Array<OverlayComponent>;
|
|
166
|
+
routes: Array<OverlayRoute>;
|
|
167
|
+
surfaces: Array<OverlaySurface>;
|
|
168
|
+
};
|
|
169
|
+
export declare const MANIFEST_VERSION = 1;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o=1;export{o as MANIFEST_VERSION};
|
package/dist/mirror.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const QUIET_MS = 500;
|
|
2
|
+
export declare const CAPTURE_MAX_MS = 8000;
|
|
3
|
+
export declare const CAPTURE_TOTAL_MS = 30000;
|
|
4
|
+
export declare const MIRROR_MAX_BYTES = 2000000;
|
|
5
|
+
export declare function serializeMirror(doc: Document, route: string, origin: string): string;
|
|
6
|
+
export declare function whenQuiet(doc: Document, quietMs?: number, maxMs?: number): Promise<"quiet" | "restless">;
|
|
7
|
+
export declare function captureMirror(frame: HTMLIFrameElement, route: string): Promise<string | null>;
|