json-schema-builder-react 0.0.7 → 0.0.8
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/README.md +9 -5
- package/dist-lib/components/PropertyEditDialog.d.ts +14 -13
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/index.cjs.map +1 -1
- package/dist-lib/index.d.ts +0 -1
- package/dist-lib/index.js +592 -533
- package/dist-lib/index.js.map +1 -1
- package/package.json +12 -13
package/README.md
CHANGED
|
@@ -292,7 +292,7 @@ If you only need to edit a single property without the full builder UI, you can
|
|
|
292
292
|
|
|
293
293
|
```tsx
|
|
294
294
|
import { useState } from 'react';
|
|
295
|
-
import { PropertyEditDialog
|
|
295
|
+
import { PropertyEditDialog } from 'json-schema-builder-react';
|
|
296
296
|
import type { PropertyData } from 'json-schema-builder-react';
|
|
297
297
|
|
|
298
298
|
function PropertyEditor() {
|
|
@@ -308,7 +308,7 @@ function PropertyEditor() {
|
|
|
308
308
|
});
|
|
309
309
|
|
|
310
310
|
return (
|
|
311
|
-
|
|
311
|
+
<>
|
|
312
312
|
<button onClick={() => setIsOpen(true)}>
|
|
313
313
|
Edit Property
|
|
314
314
|
</button>
|
|
@@ -324,14 +324,17 @@ function PropertyEditor() {
|
|
|
324
324
|
}}
|
|
325
325
|
isNewProperty={false}
|
|
326
326
|
showRegex={true}
|
|
327
|
+
typeLabels={{
|
|
328
|
+
string: 'Text',
|
|
329
|
+
number: 'Number',
|
|
330
|
+
boolean: 'Yes/No'
|
|
331
|
+
}}
|
|
327
332
|
/>
|
|
328
|
-
|
|
333
|
+
</>
|
|
329
334
|
);
|
|
330
335
|
}
|
|
331
336
|
```
|
|
332
337
|
|
|
333
|
-
**Note:** When using `PropertyEditDialog` standalone, you must wrap it with `TypeLabelsProvider`.
|
|
334
|
-
|
|
335
338
|
## API Reference
|
|
336
339
|
|
|
337
340
|
### JsonSchemaBuilder Props
|
|
@@ -365,6 +368,7 @@ function PropertyEditor() {
|
|
|
365
368
|
| `propertyLabel` | `{ singular: string, plural: string }` | `{ singular: 'Property', plural: 'Properties' }` | Custom labels |
|
|
366
369
|
| `showRegex` | `boolean` | `false` | Show regex pattern field for strings |
|
|
367
370
|
| `keyEditable` | `boolean` | `false` | Allow editing property key |
|
|
371
|
+
| `typeLabels` | `TypeLabels` | Default labels | Custom labels for property types |
|
|
368
372
|
|
|
369
373
|
### Customizing Type Labels
|
|
370
374
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { PropertyData } from "@/types/schema";
|
|
2
|
+
import type { TypeLabels } from "@/contexts/TypeLabelsContext";
|
|
2
3
|
/**
|
|
3
4
|
* PropertyEditDialog - A standalone dialog for editing a single JSON schema property
|
|
4
5
|
*
|
|
5
6
|
* @example
|
|
6
7
|
* ```tsx
|
|
7
|
-
* import { PropertyEditDialog
|
|
8
|
+
* import { PropertyEditDialog } from 'json-schema-builder-react';
|
|
8
9
|
*
|
|
9
10
|
* function MyApp() {
|
|
10
11
|
* const [isOpen, setIsOpen] = useState(false);
|
|
@@ -17,17 +18,16 @@ import type { PropertyData } from "@/types/schema";
|
|
|
17
18
|
* });
|
|
18
19
|
*
|
|
19
20
|
* return (
|
|
20
|
-
* <
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* </TypeLabelsProvider>
|
|
21
|
+
* <PropertyEditDialog
|
|
22
|
+
* property={property}
|
|
23
|
+
* open={isOpen}
|
|
24
|
+
* onOpenChange={setIsOpen}
|
|
25
|
+
* onSave={(updated) => {
|
|
26
|
+
* setProperty(updated);
|
|
27
|
+
* setIsOpen(false);
|
|
28
|
+
* }}
|
|
29
|
+
* typeLabels={{ string: 'Text', number: 'Number' }}
|
|
30
|
+
* />
|
|
31
31
|
* );
|
|
32
32
|
* }
|
|
33
33
|
* ```
|
|
@@ -45,6 +45,7 @@ interface PropertyEditDialogProps {
|
|
|
45
45
|
};
|
|
46
46
|
showRegex?: boolean;
|
|
47
47
|
keyEditable?: boolean;
|
|
48
|
+
typeLabels?: TypeLabels;
|
|
48
49
|
}
|
|
49
|
-
export default function PropertyEditDialog({ property, open, onOpenChange, onSave, isArrayItem, isNewProperty, propertyLabel, showRegex, keyEditable, }: PropertyEditDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export default function PropertyEditDialog({ property, open, onOpenChange, onSave, isArrayItem, isNewProperty, propertyLabel, showRegex, keyEditable, typeLabels: customTypeLabels, }: PropertyEditDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
50
51
|
export {};
|
package/dist-lib/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),j=require("react"),je=require("@radix-ui/react-slot"),ae=require("class-variance-authority"),ve=require("clsx"),ye=require("tailwind-merge"),u=require("lucide-react"),be=require("@radix-ui/react-tooltip"),Ne=require("@radix-ui/react-select"),we=require("@radix-ui/react-dialog"),Ce=require("@radix-ui/react-label"),ke=require("@radix-ui/react-checkbox");function F(t){const a=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const s in t)if(s!=="default"){const r=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(a,s,r.get?r:{enumerable:!0,get:()=>t[s]})}}return a.default=t,Object.freeze(a)}const v=F(j),E=F(be),w=F(Ne),L=F(we),ie=F(Ce),J=F(ke);function f(...t){return ye.twMerge(ve.clsx(t))}const Se=ae.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full 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 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input bg-background hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground 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-full px-3 text-xs",lg:"h-10 rounded-full px-8",icon:"h-9 w-9"}},defaultVariants:{variant:"default",size:"default"}}),I=v.forwardRef(({className:t,variant:a,size:s,asChild:r=!1,...i},l)=>{const n=r?je.Slot:"button";return e.jsx(n,{className:f(Se({variant:a,size:s,className:t})),ref:l,...i})});I.displayName="Button";const D=v.forwardRef(({className:t,type:a,...s},r)=>e.jsx("input",{type:a,className:f("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",t),ref:r,...s}));D.displayName="Input";const Ie=E.Provider,Te=E.Root,De=E.Trigger,ne=v.forwardRef(({className:t,sideOffset:a=4,...s},r)=>e.jsx(E.Portal,{children:e.jsx(E.Content,{ref:r,sideOffset:a,className:f("z-50 overflow-hidden rounded-md bg-popover px-3 py-1.5 text-xs text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 origin-[--radix-tooltip-content-transform-origin]",t),...s})}));ne.displayName=E.Content.displayName;const V=w.Root,H=w.Value,M=v.forwardRef(({className:t,children:a,...s},r)=>e.jsxs(w.Trigger,{ref:r,className:f("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 data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",t),...s,children:[a,e.jsx(w.Icon,{asChild:!0,children:e.jsx(u.ChevronDown,{className:"h-4 w-4 opacity-50"})})]}));M.displayName=w.Trigger.displayName;const re=v.forwardRef(({className:t,...a},s)=>e.jsx(w.ScrollUpButton,{ref:s,className:f("flex cursor-default items-center justify-center py-1",t),...a,children:e.jsx(u.ChevronUp,{className:"h-4 w-4"})}));re.displayName=w.ScrollUpButton.displayName;const le=v.forwardRef(({className:t,...a},s)=>e.jsx(w.ScrollDownButton,{ref:s,className:f("flex cursor-default items-center justify-center py-1",t),...a,children:e.jsx(u.ChevronDown,{className:"h-4 w-4"})}));le.displayName=w.ScrollDownButton.displayName;const _=v.forwardRef(({className:t,children:a,position:s="popper",...r},i)=>e.jsx(w.Portal,{children:e.jsxs(w.Content,{ref:i,className:f("relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-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 origin-[--radix-select-content-transform-origin]",s==="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",t),position:s,...r,children:[e.jsx(re,{}),e.jsx(w.Viewport,{className:f("p-1",s==="popper"&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:a}),e.jsx(le,{})]})}));_.displayName=w.Content.displayName;const qe=v.forwardRef(({className:t,...a},s)=>e.jsx(w.Label,{ref:s,className:f("px-2 py-1.5 text-sm font-semibold",t),...a}));qe.displayName=w.Label.displayName;const k=v.forwardRef(({className:t,children:a,...s},r)=>e.jsxs(w.Item,{ref:r,className:f("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",t),...s,children:[e.jsx("span",{className:"absolute right-2 flex h-3.5 w-3.5 items-center justify-center",children:e.jsx(w.ItemIndicator,{children:e.jsx(u.Check,{className:"h-4 w-4"})})}),e.jsx(w.ItemText,{children:a})]}));k.displayName=w.Item.displayName;const Pe=v.forwardRef(({className:t,...a},s)=>e.jsx(w.Separator,{ref:s,className:f("-mx-1 my-1 h-px bg-muted",t),...a}));Pe.displayName=w.Separator.displayName;const Oe=L.Root,Le=L.Portal,de=v.forwardRef(({className:t,...a},s)=>e.jsx(L.Overlay,{ref:s,className:f("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",t),...a}));de.displayName=L.Overlay.displayName;const oe=v.forwardRef(({className:t,children:a,...s},r)=>e.jsxs(Le,{children:[e.jsx(de,{}),e.jsxs(L.Content,{ref:r,className:f("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",t),...s,children:[a,e.jsxs(L.Close,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[e.jsx(u.X,{className:"h-4 w-4"}),e.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));oe.displayName=L.Content.displayName;const ce=({className:t,...a})=>e.jsx("div",{className:f("flex flex-col space-y-1.5 text-center sm:text-left",t),...a});ce.displayName="DialogHeader";const me=({className:t,...a})=>e.jsx("div",{className:f("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...a});me.displayName="DialogFooter";const ue=v.forwardRef(({className:t,...a},s)=>e.jsx(L.Title,{ref:s,className:f("text-lg font-semibold leading-none tracking-tight",t),...a}));ue.displayName=L.Title.displayName;const Re=v.forwardRef(({className:t,...a},s)=>e.jsx(L.Description,{ref:s,className:f("text-sm text-muted-foreground",t),...a}));Re.displayName=L.Description.displayName;const Ee=ae.cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"),N=v.forwardRef(({className:t,...a},s)=>e.jsx(ie.Root,{ref:s,className:f(Ee(),t),...a}));N.displayName=ie.Root.displayName;const U=v.forwardRef(({className:t,...a},s)=>e.jsx(J.Root,{ref:s,className:f("grid place-content-center 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",t),...a,children:e.jsx(J.Indicator,{className:f("grid place-content-center text-current"),children:e.jsx(u.Check,{className:"h-4 w-4"})})}));U.displayName=J.Root.displayName;const Y=v.forwardRef(({className:t,...a},s)=>e.jsx("textarea",{className:f("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base 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 md:text-sm",t),ref:s,...a}));Y.displayName="Textarea";const Fe=t=>t.trim().toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g,"_"),ze=(t,a,s=!1,r=!1)=>{const i=(o,d)=>{a({...t,[o]:d})};return{handleTitleChange:o=>{i("title",o)},handleTitleBlur:()=>{if(s&&t.title){const o=Fe(t.title);i("key",o)}},handleKeyChange:o=>{(s||r)&&i("key",o)},handleFieldChange:i,handleConstraintChange:(o,d)=>{a({...t,[o]:d})}}},X={string:"String",number:"Number",integer:"Integer",boolean:"Boolean",object:"Object",array:"Array",null:"Null",file:"File"},he=j.createContext({getTypeLabel:t=>X[t],typeLabels:X});function xe({children:t,customLabels:a={}}){const s={...X,...a},r=i=>s[i]||i;return e.jsx(he.Provider,{value:{getTypeLabel:r,typeLabels:s},children:t})}function fe(){return j.useContext(he)}function $({property:t,open:a,onOpenChange:s,onSave:r,isArrayItem:i=!1,isNewProperty:l=!1,propertyLabel:n={singular:"Property",plural:"Properties"},showRegex:m=!1,keyEditable:C=!1}){var O;const{typeLabels:o}=fe(),[d,p]=j.useState(t);j.useEffect(()=>{a&&p(t)},[t,a]);const{handleTitleChange:y,handleTitleBlur:g,handleKeyChange:x,handleFieldChange:S,handleConstraintChange:b}=ze(d,p,l,C),P=()=>{var c;(c=d.title)!=null&&c.trim()&&(r(d),s(!1))},h=()=>{p(t),s(!1)};return e.jsx(Oe,{open:a,onOpenChange:s,children:e.jsxs(oe,{className:"max-w-2xl max-h-[80vh] flex flex-col gap-0 p-0","data-testid":"dialog-edit-property",children:[e.jsx(ce,{className:"px-6 pt-6 pb-4 shrink-0",children:e.jsx(ue,{children:l?`Add ${n.singular}`:`Edit ${n.singular}`})}),e.jsxs("div",{className:"space-y-6 px-6 pb-4 overflow-y-auto flex-1 min-h-0",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(N,{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-red-500"}),"Type"]}),e.jsxs(V,{value:d.type,onValueChange:c=>S("type",c),"data-testid":"select-type-dialog",children:[e.jsx(M,{children:e.jsx(H,{})}),e.jsxs(_,{children:[e.jsx(k,{value:"string",children:o.string}),e.jsx(k,{value:"number",children:o.number}),e.jsx(k,{value:"integer",children:o.integer}),e.jsx(k,{value:"boolean",children:o.boolean}),e.jsx(k,{value:"object",children:o.object}),e.jsx(k,{value:"array",children:o.array}),e.jsx(k,{value:"file",children:o.file}),e.jsx(k,{value:"null",children:o.null})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(N,{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-red-500"}),"Title"]}),e.jsx(D,{value:d.title||"",onChange:c=>y(c.target.value),onBlur:g,placeholder:"Property Title","data-testid":"input-title-dialog",required:!0}),!l&&d.key&&e.jsxs("p",{className:"text-xs text-muted-foreground font-mono",children:["Key: ",d.key]})]}),(l||C)&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Key"}),e.jsx(D,{value:d.key,onChange:c=>x(c.target.value),placeholder:"property_key","data-testid":"input-key-dialog"}),!l&&e.jsx("p",{className:"text-xs text-yellow-600 dark:text-yellow-500",children:"⚠️ Changing the key may break existing references to this property"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Description"}),e.jsx(Y,{placeholder:"Optional description",value:d.description||"",onChange:c=>S("description",c.target.value),rows:2,"data-testid":"input-edit-description"})]}),d.type==="array"&&e.jsxs("div",{className:"space-y-2 border-l-2 border-border pl-4 mt-2",children:[e.jsxs(N,{className:"font-semibold text-xs text-muted-foreground",children:[o.array," Items"]}),d.items?e.jsxs("div",{className:"bg-muted/40 p-2 rounded",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Item Type"}),e.jsxs(V,{value:d.items.type,onValueChange:c=>p({...d,items:{...d.items,type:c}}),children:[e.jsx(M,{children:e.jsx(H,{})}),e.jsxs(_,{children:[e.jsx(k,{value:"string",children:o.string}),e.jsx(k,{value:"number",children:o.number}),e.jsx(k,{value:"integer",children:o.integer}),e.jsx(k,{value:"boolean",children:o.boolean}),e.jsx(k,{value:"object",children:o.object}),e.jsx(k,{value:"array",children:o.array}),e.jsx(k,{value:"file",children:o.file}),e.jsx(k,{value:"null",children:o.null})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Item Title"}),e.jsx(D,{value:d.items.title||"",onChange:c=>p({...d,items:{...d.items,title:c.target.value}}),placeholder:"Item Title"})]}),e.jsxs(I,{variant:"ghost",size:"sm",className:"mt-2",onClick:()=>p({...d,items:void 0}),children:["Remove ",o.array," Item Schema"]})]}):e.jsxs(I,{variant:"outline",size:"sm",onClick:()=>{p({...d,items:{id:Date.now().toString()+Math.random(),key:"item",type:"string",required:!1}})},children:["Add ",o.array," Item Schema"]})]}),!i&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{id:"prop-required",checked:d.required,onCheckedChange:c=>S("required",c),"data-testid":"checkbox-edit-required"}),e.jsx(N,{htmlFor:"prop-required",className:"cursor-pointer",children:"Required field"})]}),d.type==="string"&&e.jsxs("details",{className:"border rounded-md",children:[e.jsx("summary",{className:"p-4 cursor-pointer hover:bg-accent/50 transition-colors",children:e.jsxs("h4",{className:"text-sm font-medium inline",children:[o.string," Constraints"]})}),e.jsxs("div",{className:"space-y-4 p-4 pt-0",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"min-length",children:"Minimum Length"}),e.jsx(D,{id:"min-length",type:"number",placeholder:"0",value:d.minLength||"",onChange:c=>b("minLength",c.target.value?parseInt(c.target.value):void 0),"data-testid":"input-edit-minlength"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"max-length",children:"Maximum Length"}),e.jsx(D,{id:"max-length",type:"number",placeholder:"∞",value:d.maxLength||"",onChange:c=>b("maxLength",c.target.value?parseInt(c.target.value):void 0),"data-testid":"input-edit-maxlength"})]})]}),m&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"pattern",children:"Pattern (regex)"}),e.jsx(D,{id:"pattern",placeholder:"^[a-z]+$",value:d.pattern||"",onChange:c=>b("pattern",c.target.value),className:"font-mono text-sm","data-testid":"input-edit-pattern"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Enum Values"}),e.jsx("div",{className:"space-y-2",children:[...d.enum||[],""].map((c,q)=>{var B;return e.jsx(D,{placeholder:q===(((B=d.enum)==null?void 0:B.length)||0)?"Add new value...":"Enum value",value:c,onChange:K=>{const T=K.target.value,R=d.enum||[];if(q===R.length)T.trim()&&b("enum",[...R,T.trim()]);else if(T.trim()){const z=[...R];z[q]=T.trim(),b("enum",z)}else{const z=R.filter((Ye,pe)=>pe!==q);b("enum",z.length>0?z:void 0)}},"data-testid":`input-edit-enum-${q}`},q)})}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Enter allowed values (empty fields will be removed)"})]})]})]}),(d.type==="number"||d.type==="integer")&&e.jsxs("details",{className:"border rounded-md",children:[e.jsx("summary",{className:"p-4 cursor-pointer hover:bg-accent/50 transition-colors",children:e.jsx("h4",{className:"text-sm font-medium inline",children:"Numeric Constraints"})}),e.jsx("div",{className:"space-y-4 p-4 pt-0",children:e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"minimum",children:"Minimum Value"}),e.jsx(D,{id:"minimum",type:"number",placeholder:"-∞",value:d.minimum??"",onChange:c=>b("minimum",c.target.value?parseFloat(c.target.value):void 0),"data-testid":"input-edit-minimum"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"maximum",children:"Maximum Value"}),e.jsx(D,{id:"maximum",type:"number",placeholder:"∞",value:d.maximum??"",onChange:c=>b("maximum",c.target.value?parseFloat(c.target.value):void 0),"data-testid":"input-edit-maximum"})]})]})})]}),d.type==="array"&&e.jsxs("details",{className:"border rounded-md",children:[e.jsx("summary",{className:"p-4 cursor-pointer hover:bg-accent/50 transition-colors",children:e.jsxs("h4",{className:"text-sm font-medium inline",children:[o.array," Constraints"]})}),e.jsxs("div",{className:"space-y-4 p-4 pt-0",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"min-items",children:"Minimum Items"}),e.jsx(D,{id:"min-items",type:"number",placeholder:"0",value:d.minItems||"",onChange:c=>b("minItems",c.target.value?parseInt(c.target.value):void 0),"data-testid":"input-edit-minitems"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"max-items",children:"Maximum Items"}),e.jsx(D,{id:"max-items",type:"number",placeholder:"∞",value:d.maxItems||"",onChange:c=>b("maxItems",c.target.value?parseInt(c.target.value):void 0),"data-testid":"input-edit-maxitems"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{id:"unique-items",checked:d.uniqueItems||!1,onCheckedChange:c=>b("uniqueItems",c),"data-testid":"checkbox-edit-unique"}),e.jsx(N,{htmlFor:"unique-items",className:"cursor-pointer",children:"All items must be unique"})]})]})]})]}),e.jsxs(me,{className:"px-6 py-4 border-t bg-background shrink-0",children:[e.jsx(I,{variant:"outline",onClick:h,"data-testid":"button-cancel",children:"Cancel"}),e.jsx(I,{onClick:P,"data-testid":"button-save",disabled:!((O=d.title)!=null&&O.trim()),children:"Save Changes"})]})]})})}function se(t,a,s={}){const{allowEmpty:r=!1,onEditStart:i,onEditCancel:l}=s,[n,m]=j.useState(!1),[C,o]=j.useState(t);j.useEffect(()=>{n||o(t)},[t,n]);const d=()=>{o(t),m(!0),i==null||i()},p=x=>{o(x)},y=()=>{const x=C.trim();if(!r&&!x){o(t),m(!1);return}x!==t&&a(x),m(!1)};return{isEditing:n,value:C,startEdit:d,handleChange:p,handleBlur:y,handleKeyDown:x=>{x.key==="Enter"?y():x.key==="Escape"&&(o(t),m(!1),l==null||l())}}}function Be(t,a){const[s,r]=j.useState(!1);return{isChangingType:s,setIsChangingType:r,handleTypeChange:n=>{const m={...t,type:n};n!=="string"&&(delete m.minLength,delete m.maxLength,delete m.pattern,delete m.enum),n!=="number"&&n!=="integer"&&(delete m.minimum,delete m.maximum),n!=="array"&&(delete m.minItems,delete m.maxItems,delete m.uniqueItems,delete m.items),n!=="object"&&delete m.children,a(m),r(!1)},availableTypes:["string","number","integer","boolean","object","array","file"]}}const Z=()=>`${Date.now()}-${Math.random()}`;function ee(t={}){const{onConfirm:a,onCancel:s,createInitialData:r}=t,[i,l]=j.useState(!1),[n,m]=j.useState(null),C=y=>{const g=y??(r?r():null);m(g),l(!0)},o=()=>{l(!1),m(null),s==null||s()};return{isOpen:i,data:n,open:C,close:o,confirm:y=>{a==null||a(y),l(!1),m(null)},setIsOpen:y=>{y?l(!0):o()}}}function Ae(t,a){const s=ee({createInitialData:()=>({id:Z(),key:"",type:"string",required:!1}),onConfirm:l=>{a({...t,children:[...t.children||[],l]})}});return{addChild:()=>s.open(),updateChild:(l,n)=>{const m=t.children.map(C=>C.id===l?n:C);a({...t,children:m})},deleteChild:l=>{const n=t.children.filter(m=>m.id!==l);a({...t,children:n})},addChildDialog:{isOpen:s.isOpen,data:s.data,setIsOpen:s.setIsOpen,confirm:s.confirm}}}function G({property:t,onUpdate:a,onDelete:s,level:r=1,isArrayItem:i=!1,showRegex:l=!1,keyEditable:n=!1}){const{getTypeLabel:m,typeLabels:C}=fe(),o=ee(),d=se(t.title||t.key||"",h=>a({...t,title:h}),{allowEmpty:!1}),p=se(t.description||"",h=>a({...t,description:h||void 0}),{allowEmpty:!0}),y=Be(t,a),g=Ae(t,a),x=`h${Math.min(r,6)}`,S=t.type==="object",b=S&&t.children&&t.children.length>0,P={1:"text-lg font-semibold",2:"text-base",3:"text-base",4:"text-base",5:"text-sm",6:"text-sm"}[r]||"text-sm";return e.jsxs("div",{className:"group",children:[e.jsxs("div",{className:"flex gap-4 items-center rounded-md -mx-2 px-2 py-1 transition-colors hover:bg-accent/50",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsxs("div",{className:"flex items-start gap-3",children:[!i&&e.jsx("button",{onClick:()=>a({...t,required:!t.required}),className:"shrink-0 transition-all hover:scale-110 mt-0.5",title:t.required?"Required field - click to make optional":"Optional field - click to make required",children:t.required?e.jsx("span",{className:"block w-4 h-4 rounded-full bg-primary"}):e.jsx("span",{className:"block w-4 h-4 rounded-full border border-dashed border-gray-400"})}),d.isEditing?e.jsx(D,{value:d.value,onChange:h=>d.handleChange(h.target.value),onBlur:d.handleBlur,onKeyDown:d.handleKeyDown,autoFocus:!0,className:P,placeholder:"Enter title"}):e.jsxs("div",{className:"flex gap-2 flex-wrap flex-1",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(x,{className:`${P} cursor-pointer hover:text-primary transition-colors leading-none`,onClick:d.startEdit,children:t.title||t.key||e.jsx("span",{className:"text-muted-foreground italic",children:"unnamed"})}),y.isChangingType?e.jsxs(V,{value:t.type,onValueChange:h=>y.handleTypeChange(h),open:y.isChangingType,onOpenChange:y.setIsChangingType,children:[e.jsx(M,{className:"w-[140px] h-7",children:e.jsx(H,{})}),e.jsx(_,{children:y.availableTypes.map(h=>e.jsx(k,{value:h,children:C[h]},h))})]}):e.jsx(Ie,{children:e.jsxs(Te,{children:[e.jsx(De,{asChild:!0,children:e.jsxs("button",{onClick:()=>y.setIsChangingType(!0),className:"cursor-pointer hover:bg-accent rounded p-0.5 transition-colors",children:[t.type==="string"&&e.jsx(u.Type,{className:"w-5 h-5 text-muted-foreground"}),t.type==="number"&&e.jsx(u.Hash,{className:"w-5 h-5 text-muted-foreground"}),t.type==="integer"&&e.jsx(u.Hash,{className:"w-5 h-5 text-muted-foreground"}),t.type==="boolean"&&e.jsx(u.CheckSquare,{className:"w-5 h-5 text-muted-foreground"}),t.type==="object"&&e.jsx(u.Braces,{className:"w-5 h-5 text-muted-foreground"}),t.type==="array"&&e.jsx(u.List,{className:"w-5 h-5 text-muted-foreground"}),t.type==="file"&&e.jsx(u.FileText,{className:"w-5 h-5 text-muted-foreground"})]})}),e.jsxs(ne,{children:[m(t.type),t.type==="array"&&t.items?` of ${m(t.items.type)}`:"",e.jsx("div",{className:"text-xs text-muted-foreground mt-1",children:"Click to change type"})]})]})}),t.type==="object"&&e.jsx(I,{variant:"ghost",size:"icon",className:"opacity-0 group-hover:opacity-100 h-6 w-6",onClick:g.addChild,"data-testid":`button-add-child-${t.id}`,children:e.jsx(u.Plus,{className:"!w-5 !h-5"})})]}),e.jsx("div",{className:"flex-1",children:p.isEditing?e.jsx(D,{value:p.value,onChange:h=>p.handleChange(h.target.value),onBlur:p.handleBlur,onKeyDown:p.handleKeyDown,autoFocus:!0,className:"text-sm flex-1",placeholder:"Enter description"}):e.jsx(e.Fragment,{children:t.description?e.jsx("p",{className:"text-sm text-muted-foreground flex-1 min-w-[200px] cursor-pointer hover:text-foreground transition-colors","data-testid":`text-description-${t.id}`,onClick:p.startEdit,children:t.description}):e.jsx("p",{className:"text-sm text-muted-foreground/50 flex-1 min-w-[200px] cursor-pointer hover:text-muted-foreground italic transition-colors",onClick:p.startEdit,children:"Add description..."})})})]})]})}),e.jsxs("div",{className:"flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0",children:[e.jsx(I,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:()=>o.open(t),"data-testid":`button-edit-${t.id}`,children:e.jsx(u.Pencil,{className:"w-3 h-3"})}),S&&t.type!=="object"&&e.jsx(I,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:g.addChild,"data-testid":`button-add-child-${t.id}`,children:e.jsx(u.Plus,{className:"w-3 h-3"})}),e.jsx(I,{variant:"ghost",size:"icon",className:"h-7 w-7 text-muted-foreground hover:text-destructive",onClick:s,"data-testid":`button-delete-${t.id}`,children:e.jsx(u.Trash2,{className:"w-3 h-3"})})]})]}),b&&e.jsx("div",{className:r===1?"ml-6 mt-1 border-l-2 border-border pl-6":"ml-4 mt-1 border-l border-border pl-4",children:t.children.map(h=>e.jsx(G,{property:h,onUpdate:O=>g.updateChild(h.id,O),onDelete:()=>g.deleteChild(h.id),level:r+1,showRegex:l,keyEditable:n},h.id))}),t.type==="array"&&t.items&&e.jsxs("div",{className:r===1?"ml-6 mt-1 border-l-2 border-border pl-6":"ml-4 mt-1 border-l border-border pl-4",children:[e.jsxs("div",{className:"mb-2 text-xs text-muted-foreground font-semibold uppercase",children:[m("array")," Items"]}),e.jsx(G,{property:t.items,onUpdate:h=>a({...t,items:h}),onDelete:()=>a({...t,items:void 0}),level:r+1,isArrayItem:!0,showRegex:l,keyEditable:n})]}),e.jsx($,{property:o.data||t,open:o.isOpen,onOpenChange:o.setIsOpen,onSave:h=>{a(h),o.close()},isArrayItem:i,isNewProperty:!1,showRegex:l,keyEditable:n}),g.addChildDialog.isOpen&&g.addChildDialog.data&&e.jsx($,{property:g.addChildDialog.data,open:g.addChildDialog.isOpen,isNewProperty:!0,onOpenChange:g.addChildDialog.setIsOpen,onSave:g.addChildDialog.confirm,showRegex:l,keyEditable:n})]})}const te=v.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:f("rounded-xl border bg-card text-card-foreground shadow",t),...a}));te.displayName="Card";const Me=v.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:f("flex flex-col space-y-1.5 p-6",t),...a}));Me.displayName="CardHeader";const _e=v.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:f("font-semibold leading-none tracking-tight",t),...a}));_e.displayName="CardTitle";const $e=v.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:f("text-sm text-muted-foreground",t),...a}));$e.displayName="CardDescription";const Ke=v.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:f("p-6 pt-0",t),...a}));Ke.displayName="CardContent";const Je=v.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:f("flex items-center p-6 pt-0",t),...a}));Je.displayName="CardFooter";const Ve=()=>new Promise((t,a)=>{const s=document.createElement("input");s.type="file",s.accept=".json",s.onchange=r=>{var n;const i=(n=r.target.files)==null?void 0:n[0];if(!i){a(new Error("No file selected"));return}const l=new FileReader;l.onload=m=>{var C;try{const o=JSON.parse((C=m.target)==null?void 0:C.result);t(o)}catch{a(new Error("Invalid JSON file"))}},l.onerror=()=>a(new Error("Failed to read file")),l.readAsText(i)},s.click()}),ge=(t,a="schema.json")=>{const s=JSON.stringify(t,null,2),r=new Blob([s],{type:"application/json"}),i=URL.createObjectURL(r),l=document.createElement("a");l.href=i,l.download=a,document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(i)};function He({schema:t}){const[a,s]=j.useState(!1),r=JSON.stringify(t,null,2),i=async()=>{await navigator.clipboard.writeText(r),s(!0),setTimeout(()=>s(!1),2e3)},l=()=>{ge(t,"schema.json")};return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b",children:[e.jsx("h2",{className:"text-sm font-medium",children:"JSON Schema Output"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(I,{variant:"outline",size:"sm",onClick:i,"data-testid":"button-copy",children:a?e.jsx(u.CheckCircle2,{className:"w-4 h-4"}):e.jsx(u.Copy,{className:"w-4 h-4"})}),e.jsx(I,{variant:"outline",size:"sm",onClick:l,"data-testid":"button-download",children:e.jsx(u.Download,{className:"w-4 h-4"})})]})]}),e.jsx("div",{className:"flex-1 overflow-auto",children:e.jsx(te,{className:"m-4 bg-muted/30",children:e.jsx("pre",{className:"p-6 text-xs font-mono overflow-auto","data-testid":"text-json-output",children:e.jsx("code",{children:r})})})})]})}function Ue({title:t,description:a,version:s,onUpdate:r}){const[i,l]=j.useState(!1);return e.jsxs(te,{className:"p-4",children:[e.jsxs(I,{variant:"ghost",onClick:()=>l(!i),className:"w-full justify-between px-2 h-auto hover:bg-transparent","data-testid":"button-toggle-metadata",children:[e.jsx("h3",{className:"text-sm font-medium",children:"Schema Metadata"}),i?e.jsx(u.ChevronDown,{className:"w-4 h-4"}):e.jsx(u.ChevronRight,{className:"w-4 h-4"})]}),i&&e.jsxs("div",{className:"mt-4 space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"schema-title",className:"text-xs text-muted-foreground",children:"Title"}),e.jsx(D,{id:"schema-title",placeholder:"My Schema",value:t,onChange:n=>r("title",n.target.value),"data-testid":"input-title"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"schema-description",className:"text-xs text-muted-foreground",children:"Description"}),e.jsx(Y,{id:"schema-description",placeholder:"Describe your schema...",value:a,onChange:n=>r("description",n.target.value),className:"resize-none",rows:3,"data-testid":"input-schema-description"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"schema-version",className:"text-xs text-muted-foreground",children:"Version"}),e.jsx(D,{id:"schema-version",placeholder:"1.0.0",value:s,onChange:n=>r("version",n.target.value),"data-testid":"input-version"})]})]})]})}const A=(t,a,s=!0)=>{const r={type:"object"};s&&a&&(a.title&&(r.title=a.title),a.description&&(r.description=a.description));const i=Q(t);Object.keys(i).length>0&&(r.properties=i);const l=t.filter(n=>n.required&&n.key).map(n=>n.key);return l.length>0&&(r.required=l),r},Q=t=>{const a={};return t.forEach(s=>{if(!s.key)return;const i={type:s.type==="file"?"string":s.type};if(s.title&&(i.title=s.title),s.description&&(i.description=s.description),s.type==="file"&&(i.format="filename"),s.type==="string"&&(s.minLength!==void 0&&(i.minLength=s.minLength),s.maxLength!==void 0&&(i.maxLength=s.maxLength),s.pattern&&(i.pattern=s.pattern),s.enum&&s.enum.length>0&&(i.enum=s.enum)),(s.type==="number"||s.type==="integer")&&(s.minimum!==void 0&&(i.minimum=s.minimum),s.maximum!==void 0&&(i.maximum=s.maximum)),s.type==="array"&&(s.minItems!==void 0&&(i.minItems=s.minItems),s.maxItems!==void 0&&(i.maxItems=s.maxItems),s.uniqueItems&&(i.uniqueItems=s.uniqueItems),s.items&&(i.items=Q([s.items])[s.items.key]||{type:s.items.type})),s.type==="object"&&s.children&&s.children.length>0){i.properties=Q(s.children);const l=s.children.filter(n=>n.required&&n.key).map(n=>n.key);l.length>0&&(i.required=l)}a[s.key]=i}),a},Xe=t=>{const a={properties:[]};return(t.title||t.description)&&(a.metadata={title:typeof t.title=="string"?t.title:"",description:typeof t.description=="string"?t.description:"",version:"1.0.0"}),t.properties&&typeof t.properties=="object"&&(a.properties=W(t.properties,Array.isArray(t.required)?t.required:[])),a},W=(t,a=[])=>t?Object.entries(t).filter(([,s])=>typeof s=="object").map(([s,r])=>{const i=r;let l=typeof i.type=="string"?i.type:"string";l==="string"&&i.format==="filename"&&(l="file");const n={id:Z(),key:s,title:typeof i.title=="string"?i.title:void 0,type:l,description:typeof i.description=="string"?i.description:void 0,required:a.includes(s)};return i.minLength!==void 0&&(n.minLength=i.minLength),i.maxLength!==void 0&&(n.maxLength=i.maxLength),i.pattern&&(n.pattern=i.pattern),i.enum&&Array.isArray(i.enum)&&(n.enum=i.enum),i.minimum!==void 0&&(n.minimum=i.minimum),i.maximum!==void 0&&(n.maximum=i.maximum),i.minItems!==void 0&&(n.minItems=i.minItems),i.maxItems!==void 0&&(n.maxItems=i.maxItems),i.uniqueItems&&(n.uniqueItems=i.uniqueItems),n.type==="array"&&i.items&&typeof i.items=="object"&&!Array.isArray(i.items)&&(n.items=W({item:i.items},[]).find(m=>m.key==="item")),i.properties&&typeof i.properties=="object"&&(n.children=W(i.properties,Array.isArray(i.required)?i.required:[])),n}):[],Ge=({schema:t,onChange:a,includeMetadata:s=!0})=>{const{properties:r,metadata:i}=j.useMemo(()=>Xe(t),[t]),l=r,n=i||{title:"",description:"",version:""},m=j.useCallback(()=>({id:Z(),key:"",type:"string",required:!1}),[]),C=j.useCallback((x,S)=>{const b=l.some(O=>O.id===x);let P;b?P=l.map(O=>O.id===x?S:O):P=[...l,S];const h=A(P,n,s);a(h)},[l,n,s,a]),o=j.useCallback(x=>{const S=l.filter(P=>P.id!==x),b=A(S,n,s);a(b)},[l,n,s,a]),d=j.useCallback(()=>{const S=A([],{title:"",description:""},s);a(S)},[s,a]),p=j.useCallback((x,S)=>{const b={...n,[x]:S},P=A(l,b,s);a(P)},[l,n,s,a]),y=j.useCallback(async()=>{const x=await Ve();a(x)},[a]),g=j.useCallback(()=>{ge(t,"schema.json")},[t]);return{properties:l,metadata:n,addProperty:m,updateProperty:C,deleteProperty:o,clearAll:d,updateMetadata:p,importSchema:y,downloadSchema:g}};function Qe(){const[t,a]=j.useState("light");j.useEffect(()=>{const i=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");a(i),document.documentElement.classList.toggle("dark",i==="dark")},[]);const s=()=>{const r=t==="light"?"dark":"light";a(r),localStorage.setItem("theme",r),document.documentElement.classList.toggle("dark",r==="dark")};return e.jsx(I,{variant:"ghost",size:"icon",onClick:s,"data-testid":"button-theme-toggle",children:t==="light"?e.jsx(u.Moon,{className:"w-4 h-4"}):e.jsx(u.Sun,{className:"w-4 h-4"})})}function We({schema:t,onChange:a,showMetadata:s=!1,showImport:r=!0,showClear:i=!0,showOutput:l=!0,showHeader:n=!0,className:m="",showSummary:C=!1,typeLabels:o,propertyLabel:d={singular:"property",plural:"properties"},showRegex:p=!1,keyEditable:y=!1}){const{properties:g,metadata:x,addProperty:S,updateProperty:b,deleteProperty:P,clearAll:h,updateMetadata:O,importSchema:c}=Ge({schema:t,onChange:a,includeMetadata:s}),q=ee({createInitialData:()=>S(),onConfirm:T=>{b(T.id,T)}}),B=()=>{h()},K=async()=>{await c()};return e.jsx(xe,{customLabels:o,children:e.jsxs("div",{className:`${m} flex flex-col json-schema-builder-react`,children:[n&&e.jsx("header",{className:"h-16 border-b flex items-center justify-between px-6",children:e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx(I,{variant:"outline",size:"sm",onClick:K,"data-testid":"button-import",children:e.jsx(u.Upload,{className:"w-4 h-4"})}),i&&e.jsx(I,{variant:"outline",size:"sm",onClick:B,disabled:g.length===0,"data-testid":"button-clear",children:e.jsx(u.Trash2,{className:"w-4 h-4"})}),e.jsx(Qe,{})]})}),e.jsxs("div",{className:"flex-1 flex overflow-hidden",children:[e.jsx("div",{className:l?"w-3/5 border-r":"w-full",children:e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"flex-1 overflow-auto p-2 space-y-4",children:[s&&e.jsx(Ue,{title:x.title,description:x.description,version:x.version,onUpdate:(T,R)=>O(T,R)}),g.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 text-center",children:[e.jsx("div",{className:"w-16 h-16 rounded-full bg-muted flex items-center justify-center mb-4",children:e.jsx(u.Plus,{className:"w-8 h-8 text-muted-foreground"})}),e.jsxs("h2",{className:"text-lg font-medium mb-2",children:["No ",d.plural," yet"]}),e.jsxs("p",{className:"text-sm text-muted-foreground mb-6 max-w-sm",children:["Start building your JSON schema by adding your first"," ",d.singular]}),e.jsxs(I,{onClick:()=>q.open(),"data-testid":"button-add-first",children:[e.jsx(u.Plus,{className:"w-4 h-4 mr-2"}),"Add ",d.singular]})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"space-y-1",children:g.map(T=>e.jsx(G,{property:T,onUpdate:R=>b(T.id,R),onDelete:()=>P(T.id),showRegex:p,keyEditable:y},T.id))}),C&&e.jsxs("div",{className:"pt-4 border-t flex items-center justify-between text-sm text-muted-foreground",children:[e.jsxs("span",{children:[g.length," ",g.length===1?d.singular:d.plural]}),e.jsxs("span",{children:[g.filter(T=>T.required).length," required"]})]})]})]}),g.length>0&&e.jsx("div",{className:"border-t p-2 pt-4 bg-background",children:e.jsxs(I,{onClick:()=>q.open(),className:"w-full",variant:"outline","data-testid":"button-add-property",children:[e.jsx(u.Plus,{className:"w-4 h-4"}),"Add ",d.singular]})})]})}),l&&e.jsx("div",{className:"w-2/5",children:e.jsx(He,{schema:t})})]}),q.isOpen&&q.data&&e.jsx($,{property:q.data,open:q.isOpen,isNewProperty:!0,onOpenChange:q.setIsOpen,propertyLabel:d,onSave:q.confirm,showRegex:p,keyEditable:y})]})})}exports.JsonSchemaBuilder=We;exports.PropertyEditDialog=$;exports.TypeLabelsProvider=xe;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),y=require("react"),ge=require("@radix-ui/react-slot"),ae=require("class-variance-authority"),je=require("clsx"),ve=require("tailwind-merge"),f=require("lucide-react"),ye=require("@radix-ui/react-tooltip"),be=require("@radix-ui/react-select"),Ne=require("@radix-ui/react-dialog"),Ce=require("@radix-ui/react-label"),we=require("@radix-ui/react-checkbox");function F(t){const a=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const s in t)if(s!=="default"){const r=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(a,s,r.get?r:{enumerable:!0,get:()=>t[s]})}}return a.default=t,Object.freeze(a)}const b=F(y),E=F(ye),C=F(be),L=F(Ne),ie=F(Ce),J=F(we);function u(...t){return ve.twMerge(je.clsx(t))}const ke=ae.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full 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 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input bg-background hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground 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-full px-3 text-xs",lg:"h-10 rounded-full px-8",icon:"h-9 w-9"}},defaultVariants:{variant:"default",size:"default"}}),S=b.forwardRef(({className:t,variant:a,size:s,asChild:r=!1,...i},l)=>{const n=r?ge.Slot:"button";return e.jsx(n,{className:u(ke({variant:a,size:s,className:t})),ref:l,...i})});S.displayName="Button";const D=b.forwardRef(({className:t,type:a,...s},r)=>e.jsx("input",{type:a,className:u("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",t),ref:r,...s}));D.displayName="Input";const Se=E.Provider,Ie=E.Root,Te=E.Trigger,ne=b.forwardRef(({className:t,sideOffset:a=4,...s},r)=>e.jsx(E.Portal,{children:e.jsx(E.Content,{ref:r,sideOffset:a,className:u("z-50 overflow-hidden rounded-md bg-popover px-3 py-1.5 text-xs text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 origin-[--radix-tooltip-content-transform-origin]",t),...s})}));ne.displayName=E.Content.displayName;const V=C.Root,H=C.Value,M=b.forwardRef(({className:t,children:a,...s},r)=>e.jsxs(C.Trigger,{ref:r,className:u("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 data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",t),...s,children:[a,e.jsx(C.Icon,{asChild:!0,children:e.jsx(f.ChevronDown,{className:"h-4 w-4 opacity-50"})})]}));M.displayName=C.Trigger.displayName;const re=b.forwardRef(({className:t,...a},s)=>e.jsx(C.ScrollUpButton,{ref:s,className:u("flex cursor-default items-center justify-center py-1",t),...a,children:e.jsx(f.ChevronUp,{className:"h-4 w-4"})}));re.displayName=C.ScrollUpButton.displayName;const le=b.forwardRef(({className:t,...a},s)=>e.jsx(C.ScrollDownButton,{ref:s,className:u("flex cursor-default items-center justify-center py-1",t),...a,children:e.jsx(f.ChevronDown,{className:"h-4 w-4"})}));le.displayName=C.ScrollDownButton.displayName;const _=b.forwardRef(({className:t,children:a,position:s="popper",...r},i)=>e.jsx(C.Portal,{children:e.jsxs(C.Content,{ref:i,className:u("relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-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 origin-[--radix-select-content-transform-origin]",s==="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",t),position:s,...r,children:[e.jsx(re,{}),e.jsx(C.Viewport,{className:u("p-1",s==="popper"&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:a}),e.jsx(le,{})]})}));_.displayName=C.Content.displayName;const De=b.forwardRef(({className:t,...a},s)=>e.jsx(C.Label,{ref:s,className:u("px-2 py-1.5 text-sm font-semibold",t),...a}));De.displayName=C.Label.displayName;const w=b.forwardRef(({className:t,children:a,...s},r)=>e.jsxs(C.Item,{ref:r,className:u("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",t),...s,children:[e.jsx("span",{className:"absolute right-2 flex h-3.5 w-3.5 items-center justify-center",children:e.jsx(C.ItemIndicator,{children:e.jsx(f.Check,{className:"h-4 w-4"})})}),e.jsx(C.ItemText,{children:a})]}));w.displayName=C.Item.displayName;const qe=b.forwardRef(({className:t,...a},s)=>e.jsx(C.Separator,{ref:s,className:u("-mx-1 my-1 h-px bg-muted",t),...a}));qe.displayName=C.Separator.displayName;const Pe=L.Root,Le=L.Portal,de=b.forwardRef(({className:t,...a},s)=>e.jsx(L.Overlay,{ref:s,className:u("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",t),...a}));de.displayName=L.Overlay.displayName;const oe=b.forwardRef(({className:t,children:a,...s},r)=>e.jsxs(Le,{children:[e.jsx(de,{}),e.jsxs(L.Content,{ref:r,className:u("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",t),...s,children:[a,e.jsxs(L.Close,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[e.jsx(f.X,{className:"h-4 w-4"}),e.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));oe.displayName=L.Content.displayName;const ce=({className:t,...a})=>e.jsx("div",{className:u("flex flex-col space-y-1.5 text-center sm:text-left",t),...a});ce.displayName="DialogHeader";const me=({className:t,...a})=>e.jsx("div",{className:u("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",t),...a});me.displayName="DialogFooter";const ue=b.forwardRef(({className:t,...a},s)=>e.jsx(L.Title,{ref:s,className:u("text-lg font-semibold leading-none tracking-tight",t),...a}));ue.displayName=L.Title.displayName;const Oe=b.forwardRef(({className:t,...a},s)=>e.jsx(L.Description,{ref:s,className:u("text-sm text-muted-foreground",t),...a}));Oe.displayName=L.Description.displayName;const Re=ae.cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"),N=b.forwardRef(({className:t,...a},s)=>e.jsx(ie.Root,{ref:s,className:u(Re(),t),...a}));N.displayName=ie.Root.displayName;const U=b.forwardRef(({className:t,...a},s)=>e.jsx(J.Root,{ref:s,className:u("grid place-content-center 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",t),...a,children:e.jsx(J.Indicator,{className:u("grid place-content-center text-current"),children:e.jsx(f.Check,{className:"h-4 w-4"})})}));U.displayName=J.Root.displayName;const Y=b.forwardRef(({className:t,...a},s)=>e.jsx("textarea",{className:u("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base 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 md:text-sm",t),ref:s,...a}));Y.displayName="Textarea";const Ee=t=>t.trim().toLowerCase().replace(/[^\w\s]/g,"").replace(/\s+/g,"_"),Fe=(t,a,s=!1,r=!1)=>{const i=(p,j)=>{a({...t,[p]:j})};return{handleTitleChange:p=>{i("title",p)},handleTitleBlur:()=>{if(s&&t.title){const p=Ee(t.title);i("key",p)}},handleKeyChange:p=>{(s||r)&&i("key",p)},handleFieldChange:i,handleConstraintChange:(p,j)=>{a({...t,[p]:j})}}},X={string:"String",number:"Number",integer:"Integer",boolean:"Boolean",object:"Object",array:"Array",null:"Null",file:"File"},he=y.createContext({getTypeLabel:t=>X[t],typeLabels:X});function ze({children:t,customLabels:a={}}){const s={...X,...a},r=i=>s[i]||i;return e.jsx(he.Provider,{value:{getTypeLabel:r,typeLabels:s},children:t})}function xe(){return y.useContext(he)}function $({property:t,open:a,onOpenChange:s,onSave:r,isArrayItem:i=!1,isNewProperty:l=!1,propertyLabel:n={singular:"Property",plural:"Properties"},showRegex:c=!1,keyEditable:k=!1,typeLabels:p}){const{typeLabels:j}=xe(),m=p||j,[d,h]=y.useState(t);y.useEffect(()=>{a&&h(t)},[t,a]);const{handleTitleChange:g,handleTitleBlur:q,handleKeyChange:P,handleFieldChange:I,handleConstraintChange:v}=Fe(d,h,l,k),x=()=>{d.title?.trim()&&(r(d),s(!1))},z=()=>{h(t),s(!1)};return e.jsx(Pe,{open:a,onOpenChange:s,children:e.jsxs(oe,{className:"max-w-2xl max-h-[80vh] flex flex-col gap-0 p-0","data-testid":"dialog-edit-property",children:[e.jsx(ce,{className:"px-6 pt-6 pb-4 shrink-0",children:e.jsx(ue,{children:l?`Add ${n.singular}`:`Edit ${n.singular}`})}),e.jsxs("div",{className:"space-y-6 px-6 pb-4 overflow-y-auto flex-1 min-h-0",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(N,{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-red-500"}),"Type"]}),e.jsxs(V,{value:d.type,onValueChange:o=>I("type",o),"data-testid":"select-type-dialog",children:[e.jsx(M,{children:e.jsx(H,{})}),e.jsxs(_,{children:[e.jsx(w,{value:"string",children:m.string}),e.jsx(w,{value:"number",children:m.number}),e.jsx(w,{value:"integer",children:m.integer}),e.jsx(w,{value:"boolean",children:m.boolean}),e.jsx(w,{value:"object",children:m.object}),e.jsx(w,{value:"array",children:m.array}),e.jsx(w,{value:"file",children:m.file}),e.jsx(w,{value:"null",children:m.null})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(N,{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-1.5 h-1.5 rounded-full bg-red-500"}),"Title"]}),e.jsx(D,{value:d.title||"",onChange:o=>g(o.target.value),onBlur:q,placeholder:"Property Title","data-testid":"input-title-dialog",required:!0}),!l&&d.key&&e.jsxs("p",{className:"text-xs text-muted-foreground font-mono",children:["Key: ",d.key]})]}),(l||k)&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Key"}),e.jsx(D,{value:d.key,onChange:o=>P(o.target.value),placeholder:"property_key","data-testid":"input-key-dialog"}),!l&&e.jsx("p",{className:"text-xs text-yellow-600 dark:text-yellow-500",children:"⚠️ Changing the key may break existing references to this property"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Description"}),e.jsx(Y,{placeholder:"Optional description",value:d.description||"",onChange:o=>I("description",o.target.value),rows:2,"data-testid":"input-edit-description"})]}),d.type==="array"&&e.jsxs("div",{className:"space-y-2 border-l-2 border-border pl-4 mt-2",children:[e.jsxs(N,{className:"font-semibold text-xs text-muted-foreground",children:[m.array," Items"]}),d.items?e.jsxs("div",{className:"bg-muted/40 p-2 rounded",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Item Type"}),e.jsxs(V,{value:d.items.type,onValueChange:o=>h({...d,items:{...d.items,type:o}}),children:[e.jsx(M,{children:e.jsx(H,{})}),e.jsxs(_,{children:[e.jsx(w,{value:"string",children:m.string}),e.jsx(w,{value:"number",children:m.number}),e.jsx(w,{value:"integer",children:m.integer}),e.jsx(w,{value:"boolean",children:m.boolean}),e.jsx(w,{value:"object",children:m.object}),e.jsx(w,{value:"array",children:m.array}),e.jsx(w,{value:"file",children:m.file}),e.jsx(w,{value:"null",children:m.null})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Item Title"}),e.jsx(D,{value:d.items.title||"",onChange:o=>h({...d,items:{...d.items,title:o.target.value}}),placeholder:"Item Title"})]}),e.jsxs(S,{variant:"ghost",size:"sm",className:"mt-2",onClick:()=>h({...d,items:void 0}),children:["Remove ",m.array," Item Schema"]})]}):e.jsxs(S,{variant:"outline",size:"sm",onClick:()=>{h({...d,items:{id:Date.now().toString()+Math.random(),key:"item",type:"string",required:!1}})},children:["Add ",m.array," Item Schema"]})]}),!i&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{id:"prop-required",checked:d.required,onCheckedChange:o=>I("required",o),"data-testid":"checkbox-edit-required"}),e.jsx(N,{htmlFor:"prop-required",className:"cursor-pointer",children:"Required field"})]}),d.type==="string"&&e.jsxs("details",{className:"border rounded-md",children:[e.jsx("summary",{className:"p-4 cursor-pointer hover:bg-accent/50 transition-colors",children:e.jsxs("h4",{className:"text-sm font-medium inline",children:[m.string," Constraints"]})}),e.jsxs("div",{className:"space-y-4 p-4 pt-0",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"min-length",children:"Minimum Length"}),e.jsx(D,{id:"min-length",type:"number",placeholder:"0",value:d.minLength||"",onChange:o=>v("minLength",o.target.value?parseInt(o.target.value):void 0),"data-testid":"input-edit-minlength"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"max-length",children:"Maximum Length"}),e.jsx(D,{id:"max-length",type:"number",placeholder:"∞",value:d.maxLength||"",onChange:o=>v("maxLength",o.target.value?parseInt(o.target.value):void 0),"data-testid":"input-edit-maxlength"})]})]}),c&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"pattern",children:"Pattern (regex)"}),e.jsx(D,{id:"pattern",placeholder:"^[a-z]+$",value:d.pattern||"",onChange:o=>v("pattern",o.target.value),className:"font-mono text-sm","data-testid":"input-edit-pattern"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{children:"Enum Values"}),e.jsx("div",{className:"space-y-2",children:[...d.enum||[],""].map((o,O)=>e.jsx(D,{placeholder:O===(d.enum?.length||0)?"Add new value...":"Enum value",value:o,onChange:K=>{const T=K.target.value,R=d.enum||[];if(O===R.length)T.trim()&&v("enum",[...R,T.trim()]);else if(T.trim()){const A=[...R];A[O]=T.trim(),v("enum",A)}else{const A=R.filter((Ye,pe)=>pe!==O);v("enum",A.length>0?A:void 0)}},"data-testid":`input-edit-enum-${O}`},O))}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Enter allowed values (empty fields will be removed)"})]})]})]}),(d.type==="number"||d.type==="integer")&&e.jsxs("details",{className:"border rounded-md",children:[e.jsx("summary",{className:"p-4 cursor-pointer hover:bg-accent/50 transition-colors",children:e.jsx("h4",{className:"text-sm font-medium inline",children:"Numeric Constraints"})}),e.jsx("div",{className:"space-y-4 p-4 pt-0",children:e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"minimum",children:"Minimum Value"}),e.jsx(D,{id:"minimum",type:"number",placeholder:"-∞",value:d.minimum??"",onChange:o=>v("minimum",o.target.value?parseFloat(o.target.value):void 0),"data-testid":"input-edit-minimum"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"maximum",children:"Maximum Value"}),e.jsx(D,{id:"maximum",type:"number",placeholder:"∞",value:d.maximum??"",onChange:o=>v("maximum",o.target.value?parseFloat(o.target.value):void 0),"data-testid":"input-edit-maximum"})]})]})})]}),d.type==="array"&&e.jsxs("details",{className:"border rounded-md",children:[e.jsx("summary",{className:"p-4 cursor-pointer hover:bg-accent/50 transition-colors",children:e.jsxs("h4",{className:"text-sm font-medium inline",children:[m.array," Constraints"]})}),e.jsxs("div",{className:"space-y-4 p-4 pt-0",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"min-items",children:"Minimum Items"}),e.jsx(D,{id:"min-items",type:"number",placeholder:"0",value:d.minItems||"",onChange:o=>v("minItems",o.target.value?parseInt(o.target.value):void 0),"data-testid":"input-edit-minitems"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"max-items",children:"Maximum Items"}),e.jsx(D,{id:"max-items",type:"number",placeholder:"∞",value:d.maxItems||"",onChange:o=>v("maxItems",o.target.value?parseInt(o.target.value):void 0),"data-testid":"input-edit-maxitems"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(U,{id:"unique-items",checked:d.uniqueItems||!1,onCheckedChange:o=>v("uniqueItems",o),"data-testid":"checkbox-edit-unique"}),e.jsx(N,{htmlFor:"unique-items",className:"cursor-pointer",children:"All items must be unique"})]})]})]})]}),e.jsxs(me,{className:"px-6 py-4 border-t bg-background shrink-0",children:[e.jsx(S,{variant:"outline",onClick:z,"data-testid":"button-cancel",children:"Cancel"}),e.jsx(S,{onClick:x,"data-testid":"button-save",disabled:!d.title?.trim(),children:"Save Changes"})]})]})})}function se(t,a,s={}){const{allowEmpty:r=!1,onEditStart:i,onEditCancel:l}=s,[n,c]=y.useState(!1),[k,p]=y.useState(t);y.useEffect(()=>{n||p(t)},[t,n]);const j=()=>{p(t),c(!0),i?.()},m=g=>{p(g)},d=()=>{const g=k.trim();if(!r&&!g){p(t),c(!1);return}g!==t&&a(g),c(!1)};return{isEditing:n,value:k,startEdit:j,handleChange:m,handleBlur:d,handleKeyDown:g=>{g.key==="Enter"?d():g.key==="Escape"&&(p(t),c(!1),l?.())}}}function Ae(t,a){const[s,r]=y.useState(!1);return{isChangingType:s,setIsChangingType:r,handleTypeChange:n=>{const c={...t,type:n};n!=="string"&&(delete c.minLength,delete c.maxLength,delete c.pattern,delete c.enum),n!=="number"&&n!=="integer"&&(delete c.minimum,delete c.maximum),n!=="array"&&(delete c.minItems,delete c.maxItems,delete c.uniqueItems,delete c.items),n!=="object"&&delete c.children,a(c),r(!1)},availableTypes:["string","number","integer","boolean","object","array","file"]}}const Z=()=>`${Date.now()}-${Math.random()}`;function ee(t={}){const{onConfirm:a,onCancel:s,createInitialData:r}=t,[i,l]=y.useState(!1),[n,c]=y.useState(null),k=d=>{const h=d??(r?r():null);c(h),l(!0)},p=()=>{l(!1),c(null),s?.()};return{isOpen:i,data:n,open:k,close:p,confirm:d=>{a?.(d),l(!1),c(null)},setIsOpen:d=>{d?l(!0):p()}}}function Be(t,a){const s=ee({createInitialData:()=>({id:Z(),key:"",type:"string",required:!1}),onConfirm:l=>{a({...t,children:[...t.children||[],l]})}});return{addChild:()=>s.open(),updateChild:(l,n)=>{const c=t.children.map(k=>k.id===l?n:k);a({...t,children:c})},deleteChild:l=>{const n=t.children.filter(c=>c.id!==l);a({...t,children:n})},addChildDialog:{isOpen:s.isOpen,data:s.data,setIsOpen:s.setIsOpen,confirm:s.confirm}}}function G({property:t,onUpdate:a,onDelete:s,level:r=1,isArrayItem:i=!1,showRegex:l=!1,keyEditable:n=!1}){const{getTypeLabel:c,typeLabels:k}=xe(),p=ee(),j=se(t.title||t.key||"",x=>a({...t,title:x}),{allowEmpty:!1}),m=se(t.description||"",x=>a({...t,description:x||void 0}),{allowEmpty:!0}),d=Ae(t,a),h=Be(t,a),g=`h${Math.min(r,6)}`,q=t.type==="object",P=q&&t.children&&t.children.length>0,I={1:"text-lg font-semibold",2:"text-base",3:"text-base",4:"text-base",5:"text-sm",6:"text-sm"}[r]||"text-sm",v={1:"h-5 w-5",2:"h-4 w-4",3:"h-4 w-4",4:"h-4 w-4",5:"h-4 w-4",6:"h-4 w-4"}[r]||"h-5 w-5";return e.jsxs("div",{className:"group",children:[e.jsxs("div",{className:"flex gap-4 items-center rounded-md -mx-2 px-2 py-1 transition-colors hover:bg-accent/50",children:[e.jsx("div",{className:"flex-1 min-w-0",children:e.jsxs("div",{className:"flex items-start gap-3",children:[!i&&e.jsx("button",{onClick:()=>a({...t,required:!t.required}),className:"shrink-0 transition-all hover:scale-110 -mt-[3px]",title:t.required?"Required field - click to make optional":"Optional field - click to make required",children:t.required?e.jsx(f.Asterisk,{className:"w-6 h-6 text-primary"}):e.jsx(f.Asterisk,{className:"w-6 h-6 text-border"})}),j.isEditing?e.jsx(D,{value:j.value,onChange:x=>j.handleChange(x.target.value),onBlur:j.handleBlur,onKeyDown:j.handleKeyDown,autoFocus:!0,className:I,placeholder:"Enter title"}):e.jsxs("div",{className:"flex gap-2 flex-wrap flex-1",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(g,{className:`${I} cursor-pointer hover:text-primary transition-colors leading-none`,onClick:j.startEdit,children:t.title||t.key||e.jsx("span",{className:"text-muted-foreground italic",children:"unnamed"})}),d.isChangingType?e.jsxs(V,{value:t.type,onValueChange:x=>d.handleTypeChange(x),open:d.isChangingType,onOpenChange:d.setIsChangingType,children:[e.jsx(M,{className:"w-[140px] h-7",children:e.jsx(H,{})}),e.jsx(_,{children:d.availableTypes.map(x=>e.jsx(w,{value:x,children:k[x]},x))})]}):e.jsx(Se,{children:e.jsxs(Ie,{children:[e.jsx(Te,{asChild:!0,children:e.jsxs("button",{onClick:()=>d.setIsChangingType(!0),className:"cursor-pointer hover:bg-accent rounded p-0.5 -mt-0.5 transition-colors",children:[t.type==="string"&&e.jsx(f.Type,{className:u(v,"text-muted-foreground")}),t.type==="number"&&e.jsx(f.Hash,{className:u(v,"text-muted-foreground")}),t.type==="integer"&&e.jsx(f.Hash,{className:u(v,"text-muted-foreground")}),t.type==="boolean"&&e.jsx(f.CheckSquare,{className:u(v,"text-muted-foreground")}),t.type==="object"&&e.jsx(f.Braces,{className:u(v,"text-muted-foreground")}),t.type==="array"&&e.jsx(f.List,{className:u(v,"text-muted-foreground")}),t.type==="file"&&e.jsx(f.FileText,{className:u(v,"text-muted-foreground")})]})}),e.jsxs(ne,{children:[c(t.type),t.type==="array"&&t.items?` of ${c(t.items.type)}`:"",e.jsx("div",{className:"text-xs text-muted-foreground mt-1",children:"Click to change type"})]})]})}),t.type==="object"&&e.jsx(S,{variant:"ghost",size:"icon",className:"h-4 w-4",onClick:h.addChild,"data-testid":`button-add-child-${t.id}`,children:e.jsx(f.Plus,{})})]}),e.jsx("div",{className:"flex-1",children:m.isEditing?e.jsx(D,{value:m.value,onChange:x=>m.handleChange(x.target.value),onBlur:m.handleBlur,onKeyDown:m.handleKeyDown,autoFocus:!0,className:"text-sm flex-1",placeholder:"Enter description"}):e.jsx(e.Fragment,{children:t.description?e.jsx("p",{className:"text-sm text-muted-foreground flex-1 min-w-[200px] cursor-pointer hover:text-foreground transition-colors","data-testid":`text-description-${t.id}`,onClick:m.startEdit,children:t.description}):e.jsx("p",{className:"text-sm text-muted-foreground/50 flex-1 min-w-[200px] cursor-pointer hover:text-muted-foreground italic transition-colors",onClick:m.startEdit,children:"Add description..."})})})]})]})}),e.jsxs("div",{className:"flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity shrink-0",children:[e.jsx(S,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:()=>p.open(t),"data-testid":`button-edit-${t.id}`,children:e.jsx(f.Pencil,{className:"w-3 h-3"})}),q&&t.type!=="object"&&e.jsx(S,{variant:"ghost",size:"icon",className:"h-7 w-7",onClick:h.addChild,"data-testid":`button-add-child-${t.id}`,children:e.jsx(f.Plus,{className:"w-3 h-3"})}),e.jsx(S,{variant:"ghost",size:"icon",className:"h-7 w-7 text-muted-foreground hover:text-destructive",onClick:s,"data-testid":`button-delete-${t.id}`,children:e.jsx(f.Trash2,{className:"w-3 h-3"})})]})]}),P&&e.jsx("div",{className:r===1?"ml-6 mt-1 border-l-2 border-border pl-6":"ml-4 mt-1 border-l border-border pl-4",children:t.children.map(x=>e.jsx(G,{property:x,onUpdate:z=>h.updateChild(x.id,z),onDelete:()=>h.deleteChild(x.id),level:r+1,showRegex:l,keyEditable:n},x.id))}),t.type==="array"&&t.items&&e.jsxs("div",{className:r===1?"ml-6 mt-1 border-l-2 border-border pl-6":"ml-4 mt-1 border-l border-border pl-4",children:[e.jsxs("div",{className:"mb-2 text-xs text-muted-foreground font-semibold uppercase",children:[c("array")," Items"]}),e.jsx(G,{property:t.items,onUpdate:x=>a({...t,items:x}),onDelete:()=>a({...t,items:void 0}),level:r+1,isArrayItem:!0,showRegex:l,keyEditable:n})]}),e.jsx($,{property:p.data||t,open:p.isOpen,onOpenChange:p.setIsOpen,onSave:x=>{a(x),p.close()},isArrayItem:i,isNewProperty:!1,showRegex:l,keyEditable:n}),h.addChildDialog.isOpen&&h.addChildDialog.data&&e.jsx($,{property:h.addChildDialog.data,open:h.addChildDialog.isOpen,isNewProperty:!0,onOpenChange:h.addChildDialog.setIsOpen,onSave:h.addChildDialog.confirm,showRegex:l,keyEditable:n})]})}const te=b.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:u("rounded-xl border bg-card text-card-foreground",t),...a}));te.displayName="Card";const Me=b.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:u("flex flex-col space-y-1.5 p-6",t),...a}));Me.displayName="CardHeader";const _e=b.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:u("font-semibold leading-none tracking-tight",t),...a}));_e.displayName="CardTitle";const $e=b.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:u("text-sm text-muted-foreground",t),...a}));$e.displayName="CardDescription";const Ke=b.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:u("p-6 pt-0",t),...a}));Ke.displayName="CardContent";const Je=b.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:u("flex items-center p-6 pt-0",t),...a}));Je.displayName="CardFooter";const Ve=()=>new Promise((t,a)=>{const s=document.createElement("input");s.type="file",s.accept=".json",s.onchange=r=>{const i=r.target.files?.[0];if(!i){a(new Error("No file selected"));return}const l=new FileReader;l.onload=n=>{try{const c=JSON.parse(n.target?.result);t(c)}catch{a(new Error("Invalid JSON file"))}},l.onerror=()=>a(new Error("Failed to read file")),l.readAsText(i)},s.click()}),fe=(t,a="schema.json")=>{const s=JSON.stringify(t,null,2),r=new Blob([s],{type:"application/json"}),i=URL.createObjectURL(r),l=document.createElement("a");l.href=i,l.download=a,document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(i)};function He({schema:t}){const[a,s]=y.useState(!1),r=JSON.stringify(t,null,2),i=async()=>{await navigator.clipboard.writeText(r),s(!0),setTimeout(()=>s(!1),2e3)},l=()=>{fe(t,"schema.json")};return e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between p-4 border-b",children:[e.jsx("h2",{className:"text-sm font-medium",children:"JSON Schema Output"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(S,{variant:"outline",size:"sm",onClick:i,"data-testid":"button-copy",children:a?e.jsx(f.CheckCircle2,{className:"w-4 h-4"}):e.jsx(f.Copy,{className:"w-4 h-4"})}),e.jsx(S,{variant:"outline",size:"sm",onClick:l,"data-testid":"button-download",children:e.jsx(f.Download,{className:"w-4 h-4"})})]})]}),e.jsx("div",{className:"flex-1 overflow-auto",children:e.jsx(te,{className:"m-4 bg-muted/30",children:e.jsx("pre",{className:"p-6 text-xs font-mono overflow-auto","data-testid":"text-json-output",children:e.jsx("code",{children:r})})})})]})}function Ue({title:t,description:a,version:s,onUpdate:r}){const[i,l]=y.useState(!1);return e.jsxs(te,{className:"p-4",children:[e.jsxs(S,{variant:"ghost",onClick:()=>l(!i),className:"w-full justify-between px-2 h-auto hover:bg-transparent","data-testid":"button-toggle-metadata",children:[e.jsx("h3",{className:"text-sm font-medium",children:"Schema Metadata"}),i?e.jsx(f.ChevronDown,{className:"w-4 h-4"}):e.jsx(f.ChevronRight,{className:"w-4 h-4"})]}),i&&e.jsxs("div",{className:"mt-4 space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"schema-title",className:"text-xs text-muted-foreground",children:"Title"}),e.jsx(D,{id:"schema-title",placeholder:"My Schema",value:t,onChange:n=>r("title",n.target.value),"data-testid":"input-title"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"schema-description",className:"text-xs text-muted-foreground",children:"Description"}),e.jsx(Y,{id:"schema-description",placeholder:"Describe your schema...",value:a,onChange:n=>r("description",n.target.value),className:"resize-none",rows:3,"data-testid":"input-schema-description"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"schema-version",className:"text-xs text-muted-foreground",children:"Version"}),e.jsx(D,{id:"schema-version",placeholder:"1.0.0",value:s,onChange:n=>r("version",n.target.value),"data-testid":"input-version"})]})]})]})}const B=(t,a,s=!0)=>{const r={type:"object"};s&&a&&(a.title&&(r.title=a.title),a.description&&(r.description=a.description));const i=Q(t);Object.keys(i).length>0&&(r.properties=i);const l=t.filter(n=>n.required&&n.key).map(n=>n.key);return l.length>0&&(r.required=l),r},Q=t=>{const a={};return t.forEach(s=>{if(!s.key)return;const i={type:s.type==="file"?"string":s.type};if(s.title&&(i.title=s.title),s.description&&(i.description=s.description),s.type==="file"&&(i.format="filename"),s.type==="string"&&(s.minLength!==void 0&&(i.minLength=s.minLength),s.maxLength!==void 0&&(i.maxLength=s.maxLength),s.pattern&&(i.pattern=s.pattern),s.enum&&s.enum.length>0&&(i.enum=s.enum)),(s.type==="number"||s.type==="integer")&&(s.minimum!==void 0&&(i.minimum=s.minimum),s.maximum!==void 0&&(i.maximum=s.maximum)),s.type==="array"&&(s.minItems!==void 0&&(i.minItems=s.minItems),s.maxItems!==void 0&&(i.maxItems=s.maxItems),s.uniqueItems&&(i.uniqueItems=s.uniqueItems),s.items&&(i.items=Q([s.items])[s.items.key]||{type:s.items.type})),s.type==="object"&&s.children&&s.children.length>0){i.properties=Q(s.children);const l=s.children.filter(n=>n.required&&n.key).map(n=>n.key);l.length>0&&(i.required=l)}a[s.key]=i}),a},Xe=t=>{const a={properties:[]};return(t.title||t.description)&&(a.metadata={title:typeof t.title=="string"?t.title:"",description:typeof t.description=="string"?t.description:"",version:"1.0.0"}),t.properties&&typeof t.properties=="object"&&(a.properties=W(t.properties,Array.isArray(t.required)?t.required:[])),a},W=(t,a=[])=>t?Object.entries(t).filter(([,s])=>typeof s=="object").map(([s,r])=>{const i=r;let l=typeof i.type=="string"?i.type:"string";l==="string"&&i.format==="filename"&&(l="file");const n={id:Z(),key:s,title:typeof i.title=="string"?i.title:void 0,type:l,description:typeof i.description=="string"?i.description:void 0,required:a.includes(s)};return i.minLength!==void 0&&(n.minLength=i.minLength),i.maxLength!==void 0&&(n.maxLength=i.maxLength),i.pattern&&(n.pattern=i.pattern),i.enum&&Array.isArray(i.enum)&&(n.enum=i.enum),i.minimum!==void 0&&(n.minimum=i.minimum),i.maximum!==void 0&&(n.maximum=i.maximum),i.minItems!==void 0&&(n.minItems=i.minItems),i.maxItems!==void 0&&(n.maxItems=i.maxItems),i.uniqueItems&&(n.uniqueItems=i.uniqueItems),n.type==="array"&&i.items&&typeof i.items=="object"&&!Array.isArray(i.items)&&(n.items=W({item:i.items},[]).find(c=>c.key==="item")),i.properties&&typeof i.properties=="object"&&(n.children=W(i.properties,Array.isArray(i.required)?i.required:[])),n}):[],Ge=({schema:t,onChange:a,includeMetadata:s=!0})=>{const{properties:r,metadata:i}=y.useMemo(()=>Xe(t),[t]),l=r,n=i||{title:"",description:"",version:""},c=y.useCallback(()=>({id:Z(),key:"",type:"string",required:!1}),[]),k=y.useCallback((g,q)=>{const P=l.some(x=>x.id===g);let I;P?I=l.map(x=>x.id===g?q:x):I=[...l,q];const v=B(I,n,s);a(v)},[l,n,s,a]),p=y.useCallback(g=>{const q=l.filter(I=>I.id!==g),P=B(q,n,s);a(P)},[l,n,s,a]),j=y.useCallback(()=>{const q=B([],{title:"",description:""},s);a(q)},[s,a]),m=y.useCallback((g,q)=>{const P={...n,[g]:q},I=B(l,P,s);a(I)},[l,n,s,a]),d=y.useCallback(async()=>{const g=await Ve();a(g)},[a]),h=y.useCallback(()=>{fe(t,"schema.json")},[t]);return{properties:l,metadata:n,addProperty:c,updateProperty:k,deleteProperty:p,clearAll:j,updateMetadata:m,importSchema:d,downloadSchema:h}};function Qe(){const[t,a]=y.useState("light");y.useEffect(()=>{const i=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");a(i),document.documentElement.classList.toggle("dark",i==="dark")},[]);const s=()=>{const r=t==="light"?"dark":"light";a(r),localStorage.setItem("theme",r),document.documentElement.classList.toggle("dark",r==="dark")};return e.jsx(S,{variant:"ghost",size:"icon",onClick:s,"data-testid":"button-theme-toggle",children:t==="light"?e.jsx(f.Moon,{className:"w-4 h-4"}):e.jsx(f.Sun,{className:"w-4 h-4"})})}function We({schema:t,onChange:a,showMetadata:s=!1,showImport:r=!0,showClear:i=!0,showOutput:l=!0,showHeader:n=!0,className:c="",showSummary:k=!1,typeLabels:p,propertyLabel:j={singular:"property",plural:"properties"},showRegex:m=!1,keyEditable:d=!1}){const{properties:h,metadata:g,addProperty:q,updateProperty:P,deleteProperty:I,clearAll:v,updateMetadata:x,importSchema:z}=Ge({schema:t,onChange:a,includeMetadata:s}),o=ee({createInitialData:()=>q(),onConfirm:T=>{P(T.id,T)}}),O=()=>{v()},K=async()=>{await z()};return e.jsx(ze,{customLabels:p,children:e.jsxs("div",{className:`${c} flex flex-col json-schema-builder-react`,children:[n&&e.jsx("header",{className:"h-16 border-b flex items-center justify-between px-6",children:e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx(S,{variant:"outline",size:"sm",onClick:K,"data-testid":"button-import",children:e.jsx(f.Upload,{className:"w-4 h-4"})}),i&&e.jsx(S,{variant:"outline",size:"sm",onClick:O,disabled:h.length===0,"data-testid":"button-clear",children:e.jsx(f.Trash2,{className:"w-4 h-4"})}),e.jsx(Qe,{})]})}),e.jsxs("div",{className:"flex-1 flex overflow-hidden",children:[e.jsx("div",{className:l?"w-3/5 border-r":"w-full",children:e.jsxs("div",{className:"h-full flex flex-col",children:[e.jsxs("div",{className:"flex-1 overflow-auto p-2 space-y-4",children:[s&&e.jsx(Ue,{title:g.title,description:g.description,version:g.version,onUpdate:(T,R)=>x(T,R)}),h.length===0?e.jsxs("div",{className:"flex flex-col items-center justify-center py-16 text-center",children:[e.jsx("div",{className:"w-16 h-16 rounded-full bg-muted flex items-center justify-center mb-4",children:e.jsx(f.Plus,{className:"w-8 h-8 text-muted-foreground"})}),e.jsxs("h2",{className:"text-lg font-medium mb-2",children:["No ",j.plural," yet"]}),e.jsxs("p",{className:"text-sm text-muted-foreground mb-6 max-w-sm",children:["Start building your JSON schema by adding your first"," ",j.singular]}),e.jsxs(S,{onClick:()=>o.open(),"data-testid":"button-add-first",children:[e.jsx(f.Plus,{className:"w-4 h-4 mr-2"}),"Add ",j.singular]})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"space-y-1",children:h.map(T=>e.jsx(G,{property:T,onUpdate:R=>P(T.id,R),onDelete:()=>I(T.id),showRegex:m,keyEditable:d},T.id))}),k&&e.jsxs("div",{className:"pt-4 border-t flex items-center justify-between text-sm text-muted-foreground",children:[e.jsxs("span",{children:[h.length," ",h.length===1?j.singular:j.plural]}),e.jsxs("span",{children:[h.filter(T=>T.required).length," required"]})]})]})]}),h.length>0&&e.jsx("div",{className:"border-t p-2 pt-4 bg-background",children:e.jsxs(S,{onClick:()=>o.open(),className:"w-full",variant:"outline","data-testid":"button-add-property",children:[e.jsx(f.Plus,{className:"w-4 h-4"}),"Add ",j.singular]})})]})}),l&&e.jsx("div",{className:"w-2/5",children:e.jsx(He,{schema:t})})]}),o.isOpen&&o.data&&e.jsx($,{property:o.data,open:o.isOpen,isNewProperty:!0,onOpenChange:o.setIsOpen,propertyLabel:j,onSave:o.confirm,showRegex:m,keyEditable:d})]})})}exports.JsonSchemaBuilder=We;exports.PropertyEditDialog=$;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|