@cisri/json-schema-editor 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +303 -538
- package/dist/json-schema-editor.d.ts +1 -9
- package/dist/json-schema-editor.d.ts.map +1 -1
- package/dist/schema-utils.d.ts +24 -0
- package/dist/schema-utils.d.ts.map +1 -0
- package/package.json +16 -30
- package/dist/ui/button.d.ts +0 -12
- package/dist/ui/button.d.ts.map +0 -1
- package/dist/ui/checkbox.d.ts +0 -5
- package/dist/ui/checkbox.d.ts.map +0 -1
- package/dist/ui/input.d.ts +0 -6
- package/dist/ui/input.d.ts.map +0 -1
- package/dist/ui/select.d.ts +0 -10
- package/dist/ui/select.d.ts.map +0 -1
- package/dist/ui/table.d.ts +0 -11
- package/dist/ui/table.d.ts.map +0 -1
- package/dist/ui/textarea.d.ts +0 -6
- package/dist/ui/textarea.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),c=require("react"),xe=require("@radix-ui/react-slot"),fe=require("class-variance-authority"),d=require("@cisri/core"),ge=require("@radix-ui/react-checkbox"),j=require("lucide-react"),ye=require("@radix-ui/react-select");function M(e){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const s=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,s.get?s:{enumerable:!0,get:()=>e[t]})}}return r.default=e,Object.freeze(r)}const h=M(c),_=M(ge),x=M(ye),je=fe.cva("inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",{variants:{variant:{default:"bg-primary text-primary-foreground shadow hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",outline:"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2",sm:"h-8 rounded-md px-3 text-xs",lg:"h-10 rounded-md px-8",icon:"h-9 w-9"}},defaultVariants:{variant:"default",size:"default"}}),y=h.forwardRef(({className:e,variant:r,size:t,asChild:s=!1,...a},l)=>{const p=s?xe.Slot:"button";return n.jsx(p,{className:d.cn(je({variant:r,size:t,className:e})),ref:l,...a})});y.displayName="Button";const U=h.forwardRef(({className:e,...r},t)=>n.jsx(_.Root,{ref:t,className:d.cn("peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",e),...r,children:n.jsx(_.Indicator,{className:d.cn("flex items-center justify-center text-current"),children:n.jsx(j.Check,{className:"h-4 w-4"})})}));U.displayName=_.Root.displayName;const B=h.forwardRef(({className:e,type:r,...t},s)=>n.jsx("input",{type:r,className:d.cn("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",e),ref:s,...t}));B.displayName="Input";const we=x.Root,Ne=x.Value,K=h.forwardRef(({className:e,children:r,...t},s)=>n.jsxs(x.Trigger,{ref:s,className:d.cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span>]:line-clamp-1",e),...t,children:[r,n.jsx(x.Icon,{asChild:!0,children:n.jsx(j.ChevronDown,{className:"h-4 w-4 opacity-50"})})]}));K.displayName=x.Trigger.displayName;const Y=h.forwardRef(({className:e,children:r,position:t="popper",...s},a)=>n.jsx(x.Portal,{children:n.jsx(x.Content,{ref:a,className:d.cn("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",t==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",e),position:t,...s,children:n.jsx(x.Viewport,{className:d.cn("p-1",t==="popper"&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:r})})}));Y.displayName=x.Content.displayName;const G=h.forwardRef(({className:e,children:r,...t},s)=>n.jsxs(x.Item,{ref:s,className:d.cn("relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",e),...t,children:[n.jsx("span",{className:"absolute right-2 flex h-3.5 w-3.5 items-center justify-center",children:n.jsx(x.ItemIndicator,{children:n.jsx(j.Check,{className:"h-4 w-4"})})}),n.jsx(x.ItemText,{children:r})]}));G.displayName=x.Item.displayName;const Q=h.forwardRef(({className:e,...r},t)=>n.jsx("div",{className:"relative w-full overflow-auto",children:n.jsx("table",{ref:t,className:d.cn("w-full caption-bottom text-sm",e),...r})}));Q.displayName="Table";const W=h.forwardRef(({className:e,...r},t)=>n.jsx("thead",{ref:t,className:d.cn("[&_tr]:border-b",e),...r}));W.displayName="TableHeader";const X=h.forwardRef(({className:e,...r},t)=>n.jsx("tbody",{ref:t,className:d.cn("[&_tr:last-child]:border-0",e),...r}));X.displayName="TableBody";const ve=h.forwardRef(({className:e,...r},t)=>n.jsx("tfoot",{ref:t,className:d.cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",e),...r}));ve.displayName="TableFooter";const V=h.forwardRef(({className:e,...r},t)=>n.jsx("tr",{ref:t,className:d.cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",e),...r}));V.displayName="TableRow";const k=h.forwardRef(({className:e,...r},t)=>n.jsx("th",{ref:t,className:d.cn("h-9 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",e),...r}));k.displayName="TableHead";const C=h.forwardRef(({className:e,...r},t)=>n.jsx("td",{ref:t,className:d.cn("p-2 align-middle [&:has([role=checkbox])]:pr-0",e),...r}));C.displayName="TableCell";const Se=h.forwardRef(({className:e,...r},t)=>n.jsx("caption",{ref:t,className:d.cn("mt-4 text-sm text-muted-foreground",e),...r}));Se.displayName="TableCaption";const D=h.forwardRef(({className:e,...r},t)=>n.jsx("textarea",{className:d.cn("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",e),ref:t,...r}));D.displayName="Textarea";const ke=["object","array","string","number","integer","boolean"];let Ce=0;function Te(){return`sf-${++Ce}`}function Re(e){return e==="object"?[N("field1",{type:"string"},new Set)]:e==="array"?[N("ITEMS",{type:"string"},new Set,!0)]:[]}function N(e,r,t,s=!1){const a=r.type??"object",l=[];if(a==="object"&&r.properties){const p=new Set(r.required??[]);for(const[u,b]of Object.entries(r.properties))l.push(N(u,b,p))}else a==="array"&&r.items&&l.push(N("ITEMS",r.items,new Set,!0));return{id:Te(),name:e,type:a,required:t.has(e),description:r.description,schema:r,children:l,expanded:!0,isArrayItem:s}}function P(e){if((e.type??"object")!=="object"||!e.properties)return[];const t=new Set(e.required??[]);return Object.entries(e.properties).map(([s,a])=>N(s,a,t))}function Ie(){return N("",{type:"string"},new Set)}function q(e){return e.length>0?e:[Ie()]}function F(e){switch(e.type){case"string":return"string";case"number":case"integer":return 0;case"boolean":return!0;case"object":{const r={};if(e.properties)for(const[t,s]of Object.entries(e.properties))r[t]=F(s);return r}case"array":return e.items?[F(e.items)]:[];default:return null}}function T(e){const r={},t=[];for(const s of e)r[s.name]=Z(s),s.required&&t.push(s.name);return{type:"object",properties:r,required:t.length>0?t:void 0}}function Z(e){const r={...e.schema};if(e.type==="object"){const t=T(e.children);return{...r,type:e.type,description:e.description,properties:t.properties,required:t.required,items:void 0}}if(e.type==="array"){const t=e.children[0];return{...r,type:e.type,description:e.description,items:t?Z(t):{type:"string"},properties:void 0,required:void 0}}return{...r,type:e.type,description:e.description,properties:void 0,items:void 0,required:void 0}}function ee(e,r,t){return e.map(s=>{if(s.id===r){const a={...s,...t};return t.type&&t.type!==s.type&&(a.children=Re(t.type)),a}return s.children.length>0?{...s,children:ee(s.children,r,t)}:s})}function te(e,r){const t=e.findIndex(s=>s.id===r);if(t!==-1){const s=N(`field${e.length+1}`,{type:"string"},new Set),a=[...e];return a.splice(t+1,0,s),a}for(let s=0;s<e.length;s++)if(e[s].children.length>0){const a=te(e[s].children,r);if(a)return[...e.slice(0,s),{...e[s],children:a},...e.slice(s+1)]}return null}function re(e,r){return e.filter(t=>t.id!==r).map(t=>({...t,children:re(t.children,r)}))}function ne(e,r){return e.map(t=>t.id===r?{...t,expanded:!t.expanded}:t.children.length>0?{...t,children:ne(t.children,r)}:t)}function A(e,r){if(e===r)return!0;if(typeof e!="object"||typeof r!="object"||e==null||r==null)return!1;const t=Array.isArray(e),s=Array.isArray(r);if(t!==s)return!1;if(t){const b=e,f=r;return b.length!==f.length?!1:b.every((E,J)=>A(E,f[J]))}const a=e,l=r,p=Object.keys(a),u=Object.keys(l);return p.length!==u.length?!1:p.every(b=>A(a[b],l[b]))}function qe({level:e}){return n.jsx(n.Fragment,{children:Array.from({length:e}).map((r,t)=>n.jsx("span",{className:"inline-block w-5 shrink-0"},t))})}function Fe({value:e,"aria-label":r,disabled:t,onChange:s}){return n.jsxs(we,{value:e,onValueChange:a=>s(a),disabled:t,children:[n.jsx(K,{"aria-label":r,className:"h-7 w-28 text-xs",children:n.jsx(Ne,{})}),n.jsx(Y,{children:ke.map(a=>n.jsx(G,{value:a,className:"text-xs",children:a},a))})]})}function Ae({fieldName:e,showAdd:r,showDelete:t=!0,disableDelete:s,onAdd:a,onDelete:l}){return n.jsxs("div",{className:"flex items-center justify-end gap-1",children:[r&&n.jsx(y,{type:"button",variant:"ghost",size:"icon",className:"h-7 w-7",onClick:a,"aria-label":`在字段 ${e||"未命名"} 后添加行`,children:n.jsx(j.Plus,{className:"h-4 w-4"})}),t&&n.jsx(y,{type:"button",variant:"ghost",size:"icon",className:"h-7 w-7",disabled:s,onClick:l,"aria-label":`删除字段 ${e||"未命名"}`,children:n.jsx(j.Trash2,{className:"h-4 w-4 text-destructive"})})]})}function se({field:e,level:r,readOnly:t,disableDelete:s,dispatch:a}){const l=e.children.length>0,p=e.name||"未命名";return n.jsxs(n.Fragment,{children:[n.jsxs(V,{children:[n.jsx(C,{children:n.jsxs("div",{className:"flex items-center",children:[n.jsx(qe,{level:r}),l?n.jsx("button",{type:"button",onClick:()=>a({type:"toggleExpand",id:e.id}),className:"mr-1 inline-flex h-3.5 w-3.5 items-center justify-center text-muted-foreground","aria-label":e.expanded?"折叠":"展开",children:n.jsx(j.ChevronDown,{className:d.cn("h-3.5 w-3.5 transition-transform",!e.expanded&&"-rotate-90")})}):n.jsx(j.Minus,{className:"mr-1 h-3.5 w-3.5 text-muted-foreground/60"}),n.jsx(B,{id:`schema-name-${e.id}`,name:`schema-name-${e.id}`,"aria-label":`字段 ${p} 名称`,autoComplete:"off",disabled:t||e.isArrayItem,className:"h-7 border-transparent bg-transparent px-1 shadow-none focus-visible:bg-background disabled:opacity-100",value:e.name,onChange:u=>a({type:"update",id:e.id,patch:{name:u.target.value}})})]})}),n.jsx(C,{children:n.jsx(Fe,{value:e.type,"aria-label":`字段 ${p} 类型`,disabled:t,onChange:u=>a({type:"update",id:e.id,patch:{type:u}})})}),n.jsx(C,{children:e.isArrayItem?null:n.jsx(U,{id:`schema-required-${e.id}`,name:`schema-required-${e.id}`,"aria-label":`字段 ${p} 是否必填`,checked:e.required,disabled:t,onCheckedChange:u=>a({type:"update",id:e.id,patch:{required:u===!0}})})}),n.jsx(C,{children:n.jsx(B,{id:`schema-description-${e.id}`,name:`schema-description-${e.id}`,"aria-label":`字段 ${p} 描述`,autoComplete:"off",disabled:t,className:"h-7 border-transparent bg-transparent px-1 shadow-none focus-visible:bg-background disabled:opacity-100",value:e.description??"",onChange:u=>a({type:"update",id:e.id,patch:{description:u.target.value}})})}),n.jsx(C,{children:!t&&n.jsx(Ae,{fieldId:e.id,fieldName:e.name,showAdd:!e.isArrayItem,showDelete:!e.isArrayItem,disableDelete:s,onAdd:()=>a({type:"addSibling",id:e.id}),onDelete:()=>a({type:"delete",id:e.id})})})]}),e.expanded&&e.children.map(u=>n.jsx(se,{field:u,level:r+1,readOnly:t,disableDelete:e.type==="object"&&e.children.length<=1,dispatch:a},u.id))]})}function Ee({value:e,onChange:r,onSave:t,readOnly:s,className:a}){const[l,p]=c.useState(()=>({history:[q(P(e))],index:0})),u=l.history[l.index],b=c.useRef(l);c.useEffect(()=>{b.current=l},[l]);const[f,E]=c.useState("table"),[J,R]=c.useState(()=>JSON.stringify(e,null,2)),[H,v]=c.useState(null),[ae,z]=c.useState(null),O=c.useRef(!1),S=c.useRef(e),w=c.useMemo(()=>JSON.stringify(e,null,2),[e]);c.useEffect(()=>{if(!A(e,S.current)){const o=q(P(e));p({history:[o],index:0}),S.current=e}},[e]),c.useEffect(()=>{O.current||(R(w),v(null))},[w]),c.useEffect(()=>{z(null)},[f]);const I=c.useCallback(o=>{p(i=>A(i.history[i.index],o)?i:{history:[...i.history.slice(0,i.index+1),o],index:i.index+1})},[]),oe=c.useCallback(o=>{const i=b.current.history[b.current.index];let m;switch(o.type){case"update":m=ee(i,o.id,o.patch);break;case"addSibling":m=te(i,o.id)??i;break;case"delete":m=re(i,o.id);break;case"toggleExpand":m=ne(i,o.id);break;default:return}m=q(m);const g=T(m);S.current=g,I(m),r(g)},[r,I]),ie=l.index>0,ce=l.index<l.history.length-1,de=c.useCallback(()=>{const o=b.current;if(o.index<=0)return;const i=o.index-1,m=o.history[i],g=T(m);p({...o,index:i}),S.current=g,r(g)},[r]),le=c.useCallback(()=>{const o=b.current;if(o.index>=o.history.length-1)return;const i=o.index+1,m=o.history[i],g=T(m);p({...o,index:i}),S.current=g,r(g)},[r]),$=c.useCallback(o=>()=>{E(o),o==="json"&&(R(w),v(null))},[w]),ue=c.useCallback(o=>{const i=o.target.value;R(i);try{const m=JSON.parse(i);if(m&&typeof m=="object"&&!Array.isArray(m)){const g=q(P(m)),L=T(g);S.current=L,I(g),r(L),v(null)}else v("请输入有效的 JSON 对象。")}catch{v("JSON 解析失败,请检查格式。")}},[r,I]),me=c.useCallback(()=>{O.current=!0},[]),pe=c.useCallback(()=>{O.current=!1,R(w),v(null)},[w]),he=c.useCallback(async()=>{try{let o=w,i="已复制 json schema";f==="preview"&&(o=JSON.stringify(F(e),null,2),i="已复制 json 示例"),await navigator.clipboard.writeText(o),z(i),window.setTimeout(()=>z(null),1500)}catch{}},[w,e,f]),be=c.useCallback(()=>{t==null||t(e)},[t,e]);return n.jsxs("div",{className:d.cn("rounded-md border border-border bg-card text-card-foreground",a),children:[n.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 border-b border-border p-2",children:[n.jsxs("div",{className:"inline-flex items-center overflow-hidden rounded-md border border-border",children:[n.jsx(y,{type:"button",variant:"ghost",size:"sm",onClick:$("table"),className:d.cn("h-7 rounded-none border-r border-border text-xs",f==="table"&&"bg-muted"),children:"表格视图"}),n.jsx(y,{type:"button",variant:"ghost",size:"sm",onClick:$("json"),className:d.cn("h-7 rounded-none border-r border-border text-xs",f==="json"&&"bg-muted"),children:"JSON 视图"}),n.jsx(y,{type:"button",variant:"ghost",size:"sm",onClick:$("preview"),className:d.cn("h-7 rounded-none text-xs",f==="preview"&&"bg-muted"),children:"预览"})]}),n.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[!s&&t&&n.jsx(y,{type:"button",size:"sm",onClick:be,className:"h-7 text-xs",children:"保存"}),f!=="table"&&n.jsx(y,{type:"button",variant:"outline",size:"sm",onClick:he,className:"h-7 text-xs",children:ae??"复制"}),!s&&n.jsxs(n.Fragment,{children:[n.jsx(y,{type:"button",variant:"ghost",size:"icon",onClick:de,disabled:!ie,className:"h-7 w-7","aria-label":"撤销",children:n.jsx(j.Undo2,{className:"h-4 w-4"})}),n.jsx(y,{type:"button",variant:"ghost",size:"icon",onClick:le,disabled:!ce,className:"h-7 w-7","aria-label":"恢复",children:n.jsx(j.Redo2,{className:"h-4 w-4"})})]})]})]}),f==="json"?n.jsxs("div",{className:"space-y-2 p-2",children:[n.jsx(D,{value:J,onChange:s?void 0:ue,onFocus:s?void 0:me,onBlur:s?void 0:pe,readOnly:s,placeholder:"在此编辑或粘贴 JSON Schema...",className:"min-h-[320px] font-mono text-xs"}),H&&n.jsx("p",{className:"text-xs text-destructive",children:H})]}):f==="preview"?n.jsx("div",{className:"p-2",children:n.jsx(D,{value:JSON.stringify(F(e),null,2),readOnly:!0,className:"min-h-[320px] font-mono text-xs"})}):n.jsxs(Q,{children:[n.jsx(W,{children:n.jsxs(V,{children:[n.jsx(k,{className:"w-[28%]",children:"名称"}),n.jsx(k,{className:"w-[18%]",children:"类型"}),n.jsx(k,{className:"w-[12%]",children:"必填"}),n.jsx(k,{className:"w-[30%]",children:"描述"}),n.jsx(k,{className:"w-[12%]"})]})}),n.jsx(X,{children:u.map(o=>n.jsx(se,{field:o,level:0,readOnly:s,disableDelete:u.length<=1,dispatch:oe},o.id))})]})]})}exports.JsonSchemaEditor=Ee;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),l=require("react"),a=require("@cisri/shadcn"),w=require("@cisri/core"),S=require("lucide-react"),z=require("@cisri/json-schema-core");let ee=0;function te(){return`sf-${++ee}`}function ne(e){return e==="object"?[j("field1",{type:"string"},new Set)]:e==="array"?[j("ITEMS",{type:"string"},new Set,!0)]:[]}function j(e,n,r,s=!1,o=!1){const d=n.type??"object",h=[];if(d==="object"&&n.properties){const x=new Set(n.required??[]);for(const[m,p]of Object.entries(n.properties))h.push(j(m,p,x))}else d==="array"&&n.items&&h.push(j("ITEMS",n.items,new Set,!0));return{id:te(),name:e,type:d,required:r.has(e),description:n.description,schema:n,children:h,expanded:!0,isArrayItem:s,isRoot:o}}function J(e){const n=j(e.title??"",e,new Set,!1,!0);return n.type==="object"&&n.children.length===0&&n.children.push(j("field1",{type:"string"},new Set)),[n]}function re(){return j("",{type:"string"},new Set)}function k(e){return e.length>0?e:[re()]}function v(e){if(e.length!==1||!e[0].isRoot)throw new Error("fieldsToSchema expects exactly one root field");return B(e[0])}function B(e){const n={...e.schema};if(e.type==="object"){const r=se(e.children);return{...n,type:e.type,title:e.isRoot?e.name:n.title,description:e.description,properties:r.properties,required:r.required,items:void 0}}if(e.type==="array"){const r=e.children[0];return{...n,type:e.type,title:e.isRoot?e.name:n.title,description:e.description,items:r?B(r):{type:"string"},properties:void 0,required:void 0}}return{...n,type:e.type,title:e.isRoot?e.name:n.title,description:e.description,properties:void 0,items:void 0,required:void 0}}function se(e){const n={},r=[];for(const s of e)n[s.name]=B(s),s.required&&r.push(s.name);return{properties:n,required:r.length>0?r:void 0}}const ie=["object","array","string","number","integer","boolean"];function M(e,n,r){return e.map(s=>{if(s.id===n){const o={...s,...r};return r.type&&r.type!==s.type&&(o.children=ne(r.type)),o}return s.children.length>0?{...s,children:M(s.children,n,r)}:s})}function O(e,n){const r=e.findIndex(s=>s.id===n);if(r!==-1){const s=j(`field${e.length+1}`,{type:"string"},new Set),o=[...e];return o.splice(r+1,0,s),o}for(let s=0;s<e.length;s++)if(e[s].children.length>0){const o=O(e[s].children,n);if(o)return[...e.slice(0,s),{...e[s],children:o},...e.slice(s+1)]}return null}function D(e,n){return e.filter(r=>r.id!==n).map(r=>({...r,children:D(r.children,n)}))}function H(e,n){return e.map(r=>r.id===n?{...r,expanded:!r.expanded}:r.children.length>0?{...r,children:H(r.children,n)}:r)}function R(e,n){if(e===n)return!0;if(typeof e!="object"||typeof n!="object"||e==null||n==null)return!1;const r=Array.isArray(e),s=Array.isArray(n);if(r!==s)return!1;if(r){const m=e,p=n;return m.length!==p.length?!1:m.every((I,q)=>R(I,p[q]))}const o=e,d=n,h=Object.keys(o),x=Object.keys(d);return h.length!==x.length?!1:h.every(m=>R(o[m],d[m]))}function ae({level:e}){return t.jsx(t.Fragment,{children:Array.from({length:e}).map((n,r)=>t.jsx("span",{className:"inline-block w-5 shrink-0"},r))})}function oe({value:e,"aria-label":n,disabled:r,onChange:s}){return t.jsxs(a.Select,{value:e,onValueChange:o=>s(o),disabled:r,children:[t.jsx(a.SelectTrigger,{"aria-label":n,className:"h-7 w-28 text-xs",children:t.jsx(a.SelectValue,{})}),t.jsx(a.SelectContent,{children:ie.map(o=>t.jsx(a.SelectItem,{value:o,className:"text-xs",children:o},o))})]})}function ce({fieldName:e,showAdd:n,showDelete:r=!0,disableDelete:s,onAdd:o,onDelete:d}){return t.jsxs("div",{className:"flex items-center justify-end gap-1",children:[n&&t.jsx(a.Button,{type:"button",variant:"ghost",size:"icon",className:"h-7 w-7",onClick:o,"aria-label":`在字段 ${e||"未命名"} 后添加行`,children:t.jsx(S.Plus,{className:"h-4 w-4"})}),r&&t.jsx(a.Button,{type:"button",variant:"ghost",size:"icon",className:"h-7 w-7",disabled:s,onClick:d,"aria-label":`删除字段 ${e||"未命名"}`,children:t.jsx(S.Trash2,{className:"h-4 w-4 text-destructive"})})]})}function P({field:e,level:n,readOnly:r,disableDelete:s,dispatch:o}){const d=e.children.length>0,h=e.name||"未命名";return t.jsxs(t.Fragment,{children:[t.jsxs(a.TableRow,{className:w.cn(e.isRoot&&"bg-muted/30"),children:[t.jsx(a.TableCell,{children:t.jsxs("div",{className:"flex items-center",children:[t.jsx(ae,{level:n}),d?t.jsx("button",{type:"button",onClick:()=>o({type:"toggleExpand",id:e.id}),className:"mr-1 inline-flex h-3.5 w-3.5 items-center justify-center text-muted-foreground","aria-label":e.expanded?"折叠":"展开",children:t.jsx(S.ChevronDown,{className:w.cn("h-3.5 w-3.5 transition-transform",!e.expanded&&"-rotate-90")})}):t.jsx(S.Minus,{className:"mr-1 h-3.5 w-3.5 text-muted-foreground/60"}),t.jsx(a.Input,{id:`schema-name-${e.id}`,name:`schema-name-${e.id}`,"aria-label":`字段 ${h} 名称`,autoComplete:"off",disabled:r||e.isArrayItem,className:"h-7 border-transparent bg-transparent px-1 shadow-none focus-visible:bg-background disabled:opacity-100",value:e.name,onChange:x=>o({type:"update",id:e.id,patch:{name:x.target.value}})})]})}),t.jsx(a.TableCell,{children:t.jsx(oe,{value:e.type,"aria-label":`字段 ${h} 类型`,disabled:r,onChange:x=>o({type:"update",id:e.id,patch:{type:x}})})}),t.jsx(a.TableCell,{children:e.isArrayItem||e.isRoot?null:t.jsx(a.Checkbox,{id:`schema-required-${e.id}`,name:`schema-required-${e.id}`,"aria-label":`字段 ${h} 是否必填`,checked:e.required,disabled:r,onCheckedChange:x=>o({type:"update",id:e.id,patch:{required:x===!0}})})}),t.jsx(a.TableCell,{children:t.jsx(a.Input,{id:`schema-description-${e.id}`,name:`schema-description-${e.id}`,"aria-label":`字段 ${h} 描述`,autoComplete:"off",disabled:r,className:"h-7 border-transparent bg-transparent px-1 shadow-none focus-visible:bg-background disabled:opacity-100",value:e.description??"",onChange:x=>o({type:"update",id:e.id,patch:{description:x.target.value}})})}),t.jsx(a.TableCell,{children:!r&&!e.isRoot&&t.jsx(ce,{fieldId:e.id,fieldName:e.name,showAdd:!e.isArrayItem,showDelete:!e.isArrayItem,disableDelete:s,onAdd:()=>o({type:"addSibling",id:e.id}),onDelete:()=>o({type:"delete",id:e.id})})})]}),e.expanded&&e.children.map(x=>t.jsx(P,{field:x,level:n+1,readOnly:r,disableDelete:e.type==="object"&&e.children.length<=1,dispatch:o},x.id))]})}function le({value:e,onChange:n,onSave:r,readOnly:s,className:o}){const[d,h]=l.useState(()=>({history:[k(J(e))],index:0})),x=d.history[d.index],m=l.useRef(d);l.useEffect(()=>{m.current=d},[d]);const[p,I]=l.useState("table"),[q,C]=l.useState(()=>JSON.stringify(e,null,2)),[$,g]=l.useState(null),[V,A]=l.useState(null),E=l.useRef(!1),f=l.useRef(e),y=l.useMemo(()=>JSON.stringify(e,null,2),[e]);l.useEffect(()=>{if(!R(e,f.current)){const i=k(J(e));h({history:[i],index:0}),f.current=e}},[e]),l.useEffect(()=>{E.current||(C(y),g(null))},[y]),l.useEffect(()=>{A(null)},[p]);const T=l.useCallback(i=>{h(c=>R(c.history[c.index],i)?c:{history:[...c.history.slice(0,c.index+1),i],index:c.index+1})},[]),L=l.useCallback(i=>{const c=m.current.history[m.current.index],b=c[0];if(b&&i.id===b.id&&(i.type==="delete"||i.type==="addSibling"))return;let u;switch(i.type){case"update":u=M(c,i.id,i.patch);break;case"addSibling":u=O(c,i.id)??c;break;case"delete":u=D(c,i.id);break;case"toggleExpand":u=H(c,i.id);break;default:return}u=k(u);const N=v(u);f.current=N,T(u),n(N)},[n,T]),U=d.index>0,K=d.index<d.history.length-1,_=l.useCallback(()=>{const i=m.current;if(i.index<=0)return;const c=i.index-1,b=i.history[c],u=v(b);h({...i,index:c}),f.current=u,n(u)},[n]),Y=l.useCallback(()=>{const i=m.current;if(i.index>=i.history.length-1)return;const c=i.index+1,b=i.history[c],u=v(b);h({...i,index:c}),f.current=u,n(u)},[n]),F=l.useCallback(i=>()=>{I(i),i==="json"&&(C(y),g(null))},[y]),G=l.useCallback(i=>{const c=i.target.value;C(c);try{const b=JSON.parse(c);if(b&&typeof b=="object"&&!Array.isArray(b)){const u=k(J(b)),N=v(u);f.current=N,T(u),n(N),g(null)}else g("请输入有效的 JSON 对象。")}catch{g("JSON 解析失败,请检查格式。")}},[n,T]),Q=l.useCallback(()=>{E.current=!0},[]),W=l.useCallback(()=>{E.current=!1,C(y),g(null)},[y]),X=l.useCallback(async()=>{try{let i=y,c="已复制 json schema";p==="preview"&&(i=JSON.stringify(z.generateSampleData(e),null,2),c="已复制 json 示例"),await navigator.clipboard.writeText(i),A(c),window.setTimeout(()=>A(null),1500)}catch{}},[y,e,p]),Z=l.useCallback(()=>{r==null||r(e)},[r,e]);return t.jsxs("div",{className:w.cn("rounded-md border border-border bg-card text-card-foreground",o),children:[t.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 border-b border-border p-2",children:[t.jsxs("div",{className:"inline-flex items-center overflow-hidden rounded-md border border-border",children:[t.jsx(a.Button,{type:"button",variant:"ghost",size:"sm",onClick:F("table"),className:w.cn("h-7 rounded-none border-r border-border text-xs",p==="table"&&"bg-muted"),children:"表格视图"}),t.jsx(a.Button,{type:"button",variant:"ghost",size:"sm",onClick:F("json"),className:w.cn("h-7 rounded-none border-r border-border text-xs",p==="json"&&"bg-muted"),children:"JSON 视图"}),t.jsx(a.Button,{type:"button",variant:"ghost",size:"sm",onClick:F("preview"),className:w.cn("h-7 rounded-none text-xs",p==="preview"&&"bg-muted"),children:"预览"})]}),t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[!s&&r&&t.jsx(a.Button,{type:"button",size:"sm",onClick:Z,className:"h-7 text-xs",children:"保存"}),p!=="table"&&t.jsx(a.Button,{type:"button",variant:"outline",size:"sm",onClick:X,className:"h-7 text-xs",children:V??"复制"}),!s&&t.jsxs(t.Fragment,{children:[t.jsx(a.Button,{type:"button",variant:"ghost",size:"icon",onClick:_,disabled:!U,className:"h-7 w-7","aria-label":"撤销",children:t.jsx(S.Undo2,{className:"h-4 w-4"})}),t.jsx(a.Button,{type:"button",variant:"ghost",size:"icon",onClick:Y,disabled:!K,className:"h-7 w-7","aria-label":"恢复",children:t.jsx(S.Redo2,{className:"h-4 w-4"})})]})]})]}),p==="json"?t.jsxs("div",{className:"space-y-2 p-2",children:[t.jsx(a.Textarea,{value:q,onChange:s?void 0:G,onFocus:s?void 0:Q,onBlur:s?void 0:W,readOnly:s,placeholder:"在此编辑或粘贴 JSON Schema...",className:"min-h-[320px] font-mono text-xs"}),$&&t.jsx("p",{className:"text-xs text-destructive",children:$})]}):p==="preview"?t.jsx("div",{className:"p-2",children:t.jsx(a.Textarea,{value:JSON.stringify(z.generateSampleData(e),null,2),readOnly:!0,className:"min-h-[320px] font-mono text-xs"})}):t.jsxs(a.Table,{children:[t.jsx(a.TableHeader,{children:t.jsxs(a.TableRow,{children:[t.jsx(a.TableHead,{className:"w-[28%]",children:"名称"}),t.jsx(a.TableHead,{className:"w-[18%]",children:"类型"}),t.jsx(a.TableHead,{className:"w-[12%]",children:"必填"}),t.jsx(a.TableHead,{className:"w-[30%]",children:"描述"}),t.jsx(a.TableHead,{className:"w-[12%]"})]})}),t.jsx(a.TableBody,{children:x.map(i=>t.jsx(P,{field:i,level:0,readOnly:s,disableDelete:!0,dispatch:L},i.id))})]})]})}exports.JsonSchemaEditor=le;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { JsonSchemaEditor } from './json-schema-editor';
|
|
2
|
-
export type {
|
|
2
|
+
export type { JsonSchemaEditorProps } from './json-schema-editor';
|
|
3
|
+
export type { JsonSchema, JsonSchemaType } from '@cisri/json-schema-core';
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
|