@nice2dev/ui-forms 1.3.9 → 1.3.11

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 CHANGED
@@ -1,25 +1,55 @@
1
1
  # @nice2dev/ui-forms
2
2
 
3
- Form builder & designer React components extracted from `@nice2dev/ui`.
3
+ Schema-driven forms and the module editors of the NiceToDev ecosystem.
4
4
 
5
5
  ## Components
6
6
 
7
- - **NiceFormBuilder** — Schema-driven dynamic form builder with validation.
8
- - **NiceFormBuilderAI** — AI-augmented form builder with natural language schema generation.
9
- - **NiceFormDesigner** — Visual drag & drop form designer.
7
+ - **NiceDevelopmentStudio** — design complete modules in one place. Its explorer shows projects
8
+ (workspaces) → packages → modules → files, and templates → modules. Each part of a module opens
9
+ in its own editor: manifest, entities, translations, views, workflows, permissions, data
10
+ sources, seeds, hooks and scripts. Saving reviews the changed files and writes back only them,
11
+ keeping each file's formatting.
12
+ - **NiceSchemaForm** — an editable form generated from a Draft-07 JSON Schema or field
13
+ definitions, with live validation and a raw JSON view.
14
+ - **NiceEntityEditor** — an entity / field designer (`*.entities.json`).
15
+ - **NiceI18nEditor** — translations as a keys × languages grid.
16
+ - **NiceArrayField** — an array of objects in a grid, edited through a form built from the item
17
+ schema.
18
+
19
+ Helpers: `formSchemaToJsonSchema`, `jsonSchemaToFormItems`, `validateAgainstJsonSchema`, and
20
+ `aiFormConfigToFormFields`. The last one turns the fields generated by `NiceFormBuilderAI` /
21
+ `useFormBuilderAI` from `@nice2dev/ui-ai` into NiceSchemaForm fields.
22
+
23
+ ## The studio without React: `@nice2dev/ui-forms/studio`
24
+
25
+ The studio's core works in Node too (validators, generators, CI):
26
+
27
+ - the provider contract and an in-memory provider;
28
+ - file kinds;
29
+ - format-keeping JSON (`patchJsonText`);
30
+ - the studio's own module format.
31
+
32
+ The preset for OmniVerk seed modules is in `@nice2dev/erp-adapter/omniverk`.
33
+
34
+ ```tsx
35
+ import { NiceDevelopmentStudio, createMemoryStudioProvider } from '@nice2dev/ui-forms';
36
+
37
+ const provider = createMemoryStudioProvider({ workspaces, templates });
38
+
39
+ <NiceDevelopmentStudio provider={provider} tutorial />;
40
+ ```
10
41
 
11
42
  ## Install
12
43
 
13
44
  ```bash
14
- npm install @nice2dev/ui-forms @nice2dev/ui
45
+ npm install @nice2dev/ui-forms @nice2dev/ui @nice2dev/ui-core @nice2dev/i18n
15
46
  ```
16
47
 
17
- Requires `@nice2dev/ui` as a peer dependency (uses `NiceForm`, `NiceBaseProps`, AI hooks).
18
-
19
48
  ## Styling
20
49
 
21
- This package ships unstyled component logic. Import the shared CSS bundle once at your app entrypoint:
50
+ Import the CSS once at your app's entry point:
22
51
 
23
52
  ```tsx
24
53
  import '@nice2dev/ui/style.css';
54
+ import '@nice2dev/ui-forms/style.css';
25
55
  ```
package/dist/index.cjs CHANGED
@@ -1,3 +1,5 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),Te=require("@nice2dev/i18n"),c=require("@nice2dev/ui"),u=require("react"),W=require("@nice2dev/ui-core");function Fe(t){var r,s;const o={text:"text",email:"email",password:"password",phone:"phone",url:"url",textarea:"textarea",number:"number",date:"date",datetime:"datetime",time:"time",select:"select",multiselect:"tags",checkbox:"checkbox",toggle:"toggle",radio:"radio",slider:"slider",rating:"rating",color:"color",file:"file",image:"file"},a=[];for(const i of t.sections)for(const n of i.fields)n.type==="heading"||n.type==="paragraph"||n.type==="divider"||n.type==="spacer"||n.type==="section"||a.push({field:n.name,label:n.label||n.name,type:o[n.type]||"text",placeholder:n.placeholder,hint:n.helpText,defaultValue:n.defaultValue,required:n.required||((r=n.validations)==null?void 0:r.some(d=>d.type==="required")),disabled:n.disabled,readOnly:n.readonly,group:i.title,options:(s=n.options)==null?void 0:s.map(d=>typeof d=="string"?{label:d,value:d}:{label:d.label,value:d.value})});return a}function ce(t){var a;const o={text:"NiceTextInput",textarea:"NiceTextArea",number:"NiceNumberInput",email:"NiceTextInput",password:"NicePasswordInput",date:"NiceDateTimePicker",datetime:"NiceDateTimePicker",time:"NiceDateTimePicker",select:"NiceSelect",multiselect:"NiceTagBox",checkbox:"NiceCheckbox",toggle:"NiceToggle",radio:"NiceRadioGroup",slider:"NiceSlider",rating:"NiceRating",color:"NiceColorPicker"};return{dataField:t.name,label:{text:t.label},editorType:o[t.type]||"NiceTextInput",editorOptions:{placeholder:t.placeholder,disabled:t.disabled,readOnly:t.readonly,...t.props},colSpan:Math.ceil((t.colSpan||12)/6),validationRules:(a=t.validations)==null?void 0:a.map(r=>({type:r.type,message:r.message,...r.value!==void 0?{[r.type]:r.value}:{}})),helpText:t.helpText}}function Ie(t){const o=[];for(const a of t.sections)a.title?o.push({itemType:"group",caption:a.title,colCount:a.columns||2,items:a.fields.map(ce)}):o.push(...a.fields.map(ce));return o}function Ce(t){const o=[];t.version||o.push("Missing schema version"),t.id||o.push("Missing form ID"),(!t.sections||t.sections.length===0)&&o.push("Form must have at least one section");const a=new Set;for(const r of t.sections||[])for(const s of r.fields||[])s.id||o.push(`Field missing ID: ${s.name}`),s.name||o.push(`Field missing name: ${s.id}`),a.has(s.name)&&o.push(`Duplicate field name: ${s.name}`),a.add(s.name);return{valid:o.length===0,errors:o}}function de(t){const{t:o}=W.useNiceTranslation(),{value:a,onChange:r,readOnly:s}=t,[i,n]=u.useState(()=>{try{return a===void 0?"":JSON.stringify(a,null,2)}catch{return""}}),[d,f]=u.useState(null);return u.useEffect(()=>{try{n(a===void 0?"":JSON.stringify(a,null,2))}catch{}},[JSON.stringify(a)]),e.jsxs("div",{className:"nice-schema-form__json-field",children:[e.jsx("textarea",{className:"nice-schema-form__json-textarea",value:i,readOnly:s,spellCheck:!1,rows:Math.min(12,Math.max(3,i.split(`
2
- `).length)),onChange:y=>{const g=y.target.value;n(g);const l=g.trim();if(l===""){f(null),r(void 0);return}try{r(JSON.parse(l)),f(null)}catch(p){f(p instanceof Error?p.message:o("jsonSchemaToFormItems.invalidJson","Invalid JSON"))}}}),d&&e.jsx("div",{className:"nice-schema-form__json-error",children:d})]})}function Me(t){switch(t){case"email":return"email";case"uri":case"url":return"url";case"date":return"date";case"date-time":return"datetime";case"time":return"time";case"color":return"color";case"password":return"password";case"phone":return"phone";case"data-url":return"file";default:return"text"}}function Ae(t,o,a,r={}){const s={field:t,label:o.title??t,required:a,hint:o.description,defaultValue:o.default};if(o.enum&&o.enum.length>0)return{...s,type:"select",options:o.enum.map(i=>({label:String(i),value:i}))};switch(o.type){case"number":case"integer":return{...s,type:"number"};case"boolean":return{...s,type:"checkbox"};case"string":return{...s,type:Me(o.format)};case"array":{const i=o.items;if(i!=null&&i.enum&&i.enum.length>0)return{...s,type:"tags",options:i.enum.map(n=>({label:String(n),value:String(n)}))};if((i==null?void 0:i.type)==="object"&&i.properties&&r.renderArrayField){const n=r.renderArrayField;return{...s,render:(d,f)=>n(d??[],f,i,s.label)}}return(i==null?void 0:i.type)==="string"||(i==null?void 0:i.type)==="number"||(i==null?void 0:i.type)==="integer"?{...s,type:"tags"}:{...s,render:(n,d)=>e.jsx(de,{value:n,onChange:d})}}case"object":if(r.renderObjectField){const i=r.renderObjectField;return{...s,render:(n,d)=>i(n??{},d,o,s.label)}}return{...s,render:(i,n)=>e.jsx(de,{value:i,onChange:n})};default:return{...s,type:"text"}}}function ae(t,o={}){const{uiSchema:a,renderArrayField:r,renderObjectField:s}=o,i={renderArrayField:r,renderObjectField:s},n=t.properties??{},d=new Set(t.required??[]);return Object.keys(n).map(f=>{const y=Ae(f,n[f],d.has(f),i);return a!=null&&a[f]?{...y,...a[f]}:y})}const Oe={text:"text",textarea:"textarea",number:"number",email:"email",password:"password",phone:"phone",url:"url",date:"date",datetime:"datetime",time:"time",select:"select",multiselect:"tags",checkbox:"checkbox",toggle:"toggle",radio:"radio",slider:"slider",rating:"rating",color:"color"};function se(t,o={}){var s,i;const{uiSchema:a}=o,r=[];for(const n of t){if(n.type==="section"&&n.children){for(const y of se(n.children,o))r.push(n.label?{...y,group:n.label}:y);continue}const d=Oe[n.type];if(!d)continue;const f={field:n.name,label:n.label,type:d,required:n.required||((s=n.validations)==null?void 0:s.some(y=>y.type==="required")),placeholder:n.placeholder,hint:n.helpText,defaultValue:n.defaultValue,disabled:n.disabled,readOnly:n.readonly,options:(i=n.options)==null?void 0:i.map(y=>typeof y=="string"?{label:y,value:y}:{label:y.label,value:y.value})};r.push(a!=null&&a[n.name]?{...f,...a[n.name]}:f)}return r}function ue(t){return t==null||t===""||Array.isArray(t)&&t.length===0}function oe(t,o){const a=[],r=o.properties??{},s=new Set(o.required??[]);for(const i of Object.keys(r)){const n=r[i],d=t[i];if(s.has(i)&&ue(d)){a.push({field:i,message:`${n.title??i} is required`});continue}if(!ue(d)&&(n.enum&&!n.enum.includes(d)&&a.push({field:i,message:`${n.title??i} must be one of: ${n.enum.join(", ")}`}),(n.type==="number"||n.type==="integer")&&typeof d=="number"&&(n.minimum!==void 0&&d<n.minimum&&a.push({field:i,message:`${n.title??i} must be ≥ ${n.minimum}`}),n.maximum!==void 0&&d>n.maximum&&a.push({field:i,message:`${n.title??i} must be ≤ ${n.maximum}`})),n.type==="string"&&typeof d=="string"&&(n.minLength!==void 0&&d.length<n.minLength&&a.push({field:i,message:`${n.title??i} must be at least ${n.minLength} chars`}),n.maxLength!==void 0&&d.length>n.maxLength&&a.push({field:i,message:`${n.title??i} must be at most ${n.maxLength} chars`}),n.pattern)))try{new RegExp(n.pattern).test(d)||a.push({field:i,message:`${n.title??i} has an invalid format`})}catch{}}return a}const ee="__nafRid";function $e(t){return Array.isArray(t)?`[${t.length}]`:t&&typeof t=="object"?"{…}":t==null?"":String(t)}const me=u.forwardRef(function(o,a){const{value:r,defaultValue:s,onChange:i,itemSchema:n,title:d,readOnly:f=!1,columns:y,className:g,style:l,"data-testid":p}=o,[T,O]=c.useControllableState({value:r,defaultValue:s,fallbackValue:[],onChange:i,componentName:"NiceArrayField"}),$=n.properties??{},M=u.useMemo(()=>(y??Object.keys($)).map(C=>{const N=$[C]??{},w={field:C,header:N.title??C};return N.type==="boolean"?(w.render=V=>V?e.jsx(c.NiceIcon,{name:"check",size:14,title:"true"}):"",w.align="center"):(N.type==="array"||N.type==="object")&&(w.render=V=>$e(V)),w}),[n,y]),I=u.useMemo(()=>ae(n),[n]),_=u.useMemo(()=>T.map((D,C)=>({...D,[ee]:String(C)})),[T]),A=D=>{const{[ee]:C,...N}=D;return N},P="nice-array-field"+(g?` ${g}`:"");return e.jsx("div",{ref:a,className:P,style:l,"data-testid":p,children:e.jsx(c.NiceDataGrid,{data:_,keyField:ee,columns:M,editMode:"popup",formItems:I,editFormTitle:d?`${d} — item`:"Edit item",emptyText:`No items${d?` in ${d}`:""}`,compact:!0,onRowAdd:f?void 0:D=>O([...T,A(D)]),onRowEdit:f?void 0:(D,C)=>{const N=Number(D);O(T.map((w,V)=>V===N?A(C):w))},onRowDelete:f?void 0:D=>{const C=Number(D);O(T.filter((N,w)=>w!==C))}})})}),De=[{target:".nice-schema-form",titleKey:"tutorial.schemaForm.intro.title",title:"Schema form",contentKey:"tutorial.schemaForm.intro.content",content:"This form is generated from a schema. Required fields and validation errors are flagged; use the JSON toggle for raw editing.",placement:"auto"},{target:'[data-tour="sf-viewtoggle"]',titleKey:"tutorial.schemaForm.viewToggle.title",title:"Form ⇄ JSON",contentKey:"tutorial.schemaForm.viewToggle.content",content:"Switch between the visual form and the raw JSON value — handy for power users and copy/paste.",placement:"bottom"},{target:".nice-schema-form",titleKey:"tutorial.schemaForm.validation.title",title:"Live validation",contentKey:"tutorial.schemaForm.validation.content",content:"Values are validated against the schema as you type; any problems are listed below the form.",placement:"auto"}];function Ke(t){const o=[],a=r=>{for(const s of r){if(s.type==="section"&&s.children){a(s.children);continue}s.required&&o.push({id:`${s.name}-required`,field:s.name,op:"required"});for(const i of s.validations??[])o.push({id:`${s.name}-${i.type}`,field:s.name,op:i.type,value:typeof i.value=="boolean"?void 0:i.value,message:i.message??(i.type==="required"?`${s.label??s.name} is required`:void 0)})}};return a(t),o}function Le(t,o){return c.evaluateValidation(Ke(t),o).filter(a=>a.severity==="error").map(a=>({field:a.field,message:a.message}))}const X=u.forwardRef(function(o,a){const{schema:r,fields:s,uiSchema:i,value:n,defaultValue:d,onChange:f,onValidate:y,showJsonView:g=!1,columns:l=1,labelPosition:p="top",readOnly:T=!1,liveValidation:O=!0,validationRules:$,tutorial:M,className:I,style:_,id:A,"data-testid":P}=o,{t:D}=c.useNiceTranslation(),[C,N]=c.useControllableState({value:n,defaultValue:d,fallbackValue:{},onChange:f,componentName:"NiceSchemaForm"}),[w,V]=u.useState(!1),[z,K]=u.useState(""),[k,J]=u.useState(null),j=u.useMemo(()=>r?ae(r,{uiSchema:i,renderArrayField:(E,b,F,q)=>e.jsx(me,{value:E,onChange:b,itemSchema:F,title:q,readOnly:T})}):s?se(s,{uiSchema:i}):[],[r,s,i,T]),R=u.useMemo(()=>{const E=r?oe(C,r):s?Le(s,C):[];if($!=null&&$.length){const b=c.evaluateValidation($,C).filter(F=>F.severity==="error").map(F=>({field:F.field,message:F.message}));return[...E,...b]}return E},[r,s,C,$]);u.useEffect(()=>{y==null||y(R)},[R,y]),u.useEffect(()=>{if(w)try{K(JSON.stringify(C,null,2)),J(null)}catch{}},[w,C]);const h=(E,b)=>{N({...C,[E]:b})},x="nice-schema-form"+(I?` ${I}`:"");return e.jsxs("div",{ref:a,id:A,className:x,style:_,"data-testid":P,children:[M&&e.jsx("div",{className:"nice-schema-form__tutorial",children:e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(M,De)})}),g&&e.jsxs("div",{className:"nice-schema-form__toolbar","data-tour":"sf-viewtoggle",children:[e.jsx("button",{type:"button",className:"nice-schema-form__tab"+(w?"":" nice-schema-form__tab--active"),onClick:()=>V(!1),children:D("schemaForm.tab.form","Form")}),e.jsx(c.NiceTooltip,{content:D("schemaForm.tab.json.help","Edit the raw JSON value directly"),children:e.jsx("button",{type:"button",className:"nice-schema-form__tab"+(w?" nice-schema-form__tab--active":""),onClick:()=>V(!0),children:D("schemaForm.tab.json","JSON")})})]}),w?e.jsxs("div",{className:"nice-schema-form__json",children:[e.jsx("textarea",{className:"nice-schema-form__json-textarea",value:z,readOnly:T,spellCheck:!1,rows:Math.min(24,Math.max(6,z.split(`
3
- `).length)),onChange:E=>{const b=E.target.value;K(b);try{const F=JSON.parse(b);J(null),N(F)}catch(F){J(F instanceof Error?F.message:D("schemaForm.invalidJson","Invalid JSON"))}}}),k&&e.jsx("div",{className:"nice-schema-form__json-error",children:k})]}):e.jsx(c.NiceForm,{items:j,data:C,onFieldChange:h,columns:l,labelPosition:p,readOnly:T}),O&&R.length>0&&e.jsx("ul",{className:"nice-schema-form__errors",role:"alert",children:R.map((E,b)=>e.jsx("li",{className:"nice-schema-form__error",children:E.message},`${E.field}-${b}`))})]})}),Re=[{name:"Contact Form",description:"A simple contact form with name, email, and message"},{name:"Registration Form",description:"User registration with username, email, password, and profile info"},{name:"Survey Form",description:"Customer satisfaction survey with rating and feedback fields"},{name:"Order Form",description:"Product order form with shipping address and payment details"},{name:"Job Application",description:"Job application with personal info, experience, and file uploads"},{name:"Event Registration",description:"Event sign-up with attendee info and preferences"}];function qe(t){return{text:"text",string:"text",textarea:"textarea",number:"number",integer:"number",email:"email",password:"password",phone:"phone",tel:"phone",url:"url",date:"date",datetime:"datetime",time:"time",select:"select",dropdown:"select",multiselect:"multiselect",checkbox:"checkbox",boolean:"checkbox",toggle:"toggle",switch:"toggle",radio:"radio",slider:"slider",range:"slider",rating:"rating",stars:"rating",color:"color",file:"file",upload:"file",signature:"signature"}[t.toLowerCase()]||"text"}function Ve(t){return t.map((o,a)=>{var r;return{id:`field_${Date.now()}_${a}`,type:qe(o.type),label:o.label,name:o.field,placeholder:o.placeholder,helperText:o.helpText,required:o.required,options:(r=o.options)==null?void 0:r.map((s,i)=>({value:s.toLowerCase().replace(/\s+/g,"_"),label:s})),validation:o.required?[{type:"required",message:`${o.label} is required`}]:[],width:"100%",order:a}})}const Be=u.forwardRef(function(o,a){const{enableAI:r=!0,aiModel:s,enableGenerate:i=!0,enableSuggestions:n=!0,onGenerate:d,showAIToolbar:f=!0,templates:y=Re,fields:g,onChange:l}=o,[p,T]=u.useState(!1),[O,$]=u.useState(""),[M,I]=u.useState([]),[_,A]=u.useState(g||[]),[P,D]=u.useState(!1),[C,N]=u.useState({}),{t:w}=Te.useNiceTranslation(),V=c.useNiceAI(),{generateForm:z,isLoading:K}=c.useFormGeneration(),k=r&&V.isConfigured,J=u.useCallback(async b=>{if(!k||!i||!b.trim())return[];try{const F=await z(b);return I(F),d==null||d(b,F),F}catch{return[]}},[k,i,z,d]),j=u.useCallback(b=>{const F=Ve(b);A(q=>[...q,...F]),l==null||l([..._,...F]),T(!1),I([]),$("")},[l,_]),R=u.useCallback(()=>_,[_]),h=u.useCallback(()=>{A([]),l==null||l([])},[l]),x=b=>{$(b.description),D(!1),J(b.description)};u.useImperativeHandle(a,()=>({generateForm:J,getFields:R,applyFields:j,clearFields:h}));const E=b=>({text:"edit",textarea:"file",number:"hash",email:"mail",password:"lock",phone:"phone",date:"calendar",select:"list",checkbox:"check",toggle:"settings",radio:"circle",file:"paperclip",rating:"star"})[b]||"edit";return e.jsxs("div",{className:"nice-form-builder-ai","data-testid":o["data-testid"],children:[f&&k&&e.jsxs("div",{className:"nice-form-builder-ai__toolbar",children:[e.jsxs("div",{className:"nice-form-builder-ai__toolbar-left",children:[e.jsx("span",{className:"nice-form-builder-ai__badge",children:w("formBuilderAI.ai","AI")}),K&&e.jsx("span",{className:"nice-form-builder-ai__loading",children:w("formBuilderAI.generating","Generating...")})]}),e.jsxs("div",{className:"nice-form-builder-ai__toolbar-right",children:[i&&e.jsxs("button",{type:"button",className:"nice-form-builder-ai__btn",onClick:()=>T(!0),disabled:K,children:[e.jsx(c.NiceIcon,{name:"zap",size:"sm"})," ",w("formBuilderAI.generateForm","Generate Form")]}),e.jsxs("div",{className:"nice-form-builder-ai__templates-dropdown",children:[e.jsxs("button",{type:"button",className:"nice-form-builder-ai__btn nice-form-builder-ai__btn--secondary",onClick:()=>D(!P),children:[e.jsx(c.NiceIcon,{name:"list",size:"sm"})," ",w("formBuilderAI.templates","Templates")," ",e.jsx(c.NiceIcon,{name:"chevron-down",size:"sm"})]}),P&&e.jsx("div",{className:"nice-form-builder-ai__templates-menu",children:y.map((b,F)=>e.jsxs("button",{type:"button",className:"nice-form-builder-ai__template-item",onClick:()=>x(b),children:[e.jsx("span",{className:"nice-form-builder-ai__template-name",children:b.name}),e.jsx("span",{className:"nice-form-builder-ai__template-desc",children:b.description})]},F))})]})]})]}),e.jsx("div",{className:"nice-form-builder-ai__builder-wrapper",children:e.jsx(X,{fields:_,value:C,onChange:N,columns:1})}),p&&e.jsxs("div",{className:"nice-form-builder-ai__panel",children:[e.jsx("div",{role:"presentation",className:"nice-form-builder-ai__panel-overlay",onClick:()=>T(!1)}),e.jsxs("div",{className:"nice-form-builder-ai__panel-content",children:[e.jsxs("div",{className:"nice-form-builder-ai__panel-header",children:[e.jsxs("h4",{children:[e.jsx(c.NiceIcon,{name:"zap",size:"sm"})," ",w("formBuilderAI.generateFormTitle","Generate Form with AI")]}),e.jsx("button",{type:"button",className:"nice-form-builder-ai__panel-close",onClick:()=>{T(!1),I([]),$("")},"aria-label":w("formBuilderAI.close","Close"),children:e.jsx(c.NiceIcon,{name:"close",size:"sm"})})]}),e.jsxs("div",{className:"nice-form-builder-ai__panel-body",children:[e.jsxs("div",{className:"nice-form-builder-ai__prompt-section",children:[e.jsx("label",{className:"nice-form-builder-ai__label",children:w("formBuilderAI.describeForm","Describe the form you want to create:")}),e.jsx("textarea",{className:"nice-form-builder-ai__textarea",placeholder:w("formBuilderAI.promptPlaceholder",'e.g., "A contact form with name, email, phone, subject dropdown, and message textarea"'),value:O,onChange:b=>$(b.target.value),rows:3}),e.jsx("button",{type:"button",className:"nice-form-builder-ai__generate-btn",onClick:()=>J(O),disabled:K||!O.trim(),children:K?w("formBuilderAI.generating","Generating..."):w("formBuilderAI.generate","Generate")})]}),M.length>0&&e.jsxs("div",{className:"nice-form-builder-ai__preview-section",children:[e.jsx("h5",{children:w("formBuilderAI.previewCount","Preview ({count} fields)").replace("{count}",String(M.length))}),e.jsx("div",{className:"nice-form-builder-ai__fields-preview",children:M.map((b,F)=>e.jsxs("div",{className:"nice-form-builder-ai__field-preview",children:[e.jsx("span",{className:"nice-form-builder-ai__field-icon",children:e.jsx(c.NiceIcon,{name:E(b.type),size:"sm"})}),e.jsxs("div",{className:"nice-form-builder-ai__field-info",children:[e.jsxs("span",{className:"nice-form-builder-ai__field-label",children:[b.label,b.required&&e.jsx("span",{className:"nice-form-builder-ai__required",children:"*"})]}),e.jsx("span",{className:"nice-form-builder-ai__field-type",children:b.type})]}),b.options&&e.jsx("span",{className:"nice-form-builder-ai__field-options",children:w("formBuilderAI.options","{options} options").replace("{options}",String(b.options.length))})]},F))})]})]}),e.jsxs("div",{className:"nice-form-builder-ai__panel-footer",children:[e.jsxs("button",{type:"button",className:"nice-form-builder-ai__apply-btn",onClick:()=>j(M),disabled:M.length===0||K,children:[e.jsx(c.NiceIcon,{name:"check",size:"sm"})," ",w("formBuilderAI.addToForm","Add to Form")]}),e.jsx("button",{type:"button",className:"nice-form-builder-ai__cancel-btn",onClick:()=>{T(!1),I([]),$("")},children:w("formBuilderAI.cancel","Cancel")})]})]})]})]})}),Pe={text:{type:"string"},textarea:{type:"string"},password:{type:"string",format:"password"},phone:{type:"string",format:"phone"},url:{type:"string",format:"uri"},email:{type:"string",format:"email"},date:{type:"string",format:"date"},datetime:{type:"string",format:"date-time"},time:{type:"string",format:"time"},color:{type:"string",format:"color"},number:{type:"number"},slider:{type:"number"},rating:{type:"integer"},checkbox:{type:"boolean"},toggle:{type:"boolean"},select:{type:"string"},radio:{type:"string"},multiselect:{type:"array",items:{type:"string"}},file:{type:"string",format:"data-url"},signature:{type:"string",format:"data-url"},richtext:{type:"string"},markdown:{type:"string"},code:{type:"string"},image:{type:"string",format:"uri"}};function ze(t,o){if(o)for(const a of o)switch(a.type){case"minLength":typeof a.value=="number"&&(t.minLength=a.value);break;case"maxLength":typeof a.value=="number"&&(t.maxLength=a.value);break;case"min":typeof a.value=="number"&&(t.minimum=a.value);break;case"max":typeof a.value=="number"&&(t.maximum=a.value);break;case"pattern":typeof a.value=="string"&&(t.pattern=a.value);break;case"email":t.format="email";break;case"url":t.format="uri";break}}function Je(t){if(t.type==="heading"||t.type==="paragraph"||t.type==="divider"||t.type==="spacer")return null;const o=Pe[t.type];if(!o)return null;const a={...o};return t.label&&(a.title=t.label),t.helpText&&(a.description=t.helpText),t.defaultValue!==void 0&&(a.default=t.defaultValue),t.options&&(t.type==="select"||t.type==="radio")&&(a.enum=t.options.map(r=>typeof r=="string"?r:r.value)),t.options&&t.type==="multiselect"&&(a.items={type:"string",enum:t.options.map(r=>typeof r=="string"?r:String(r.value))}),ze(a,t.validations),a}function Ue(t){const o={},a=[],r=i=>{var n;for(const d of i){if(d.type==="section"&&d.children){r(d.children);continue}const f=Je(d);f&&(o[d.name]=f,(d.required||(n=d.validations)!=null&&n.some(y=>y.type==="required"))&&a.push(d.name))}};for(const i of t.sections)r(i.fields);const s={$schema:"http://json-schema.org/draft-07/schema#",$id:t.id,type:"object",title:t.title,description:t.description,properties:o,additionalProperties:!1};return a.length>0&&(s.required=a),s}const He=[{target:".nice-manifest-editor",titleKey:"tutorial.manifestEditor.intro.title",title:"Manifest editor",contentKey:"tutorial.manifestEditor.intro.content",content:"Edit the manifest in schema-driven sections. Toggle Form ⇄ JSON per section; validation appears in the status bar.",placement:"auto"},{target:".nice-manifest-editor__pane",titleKey:"tutorial.manifestEditor.sections.title",title:"Sections",contentKey:"tutorial.manifestEditor.sections.content",content:"The manifest is split into schema-driven sections — switch between them using the tabs at the top.",placement:"auto"},{target:".nice-manifest-editor__pane",titleKey:"tutorial.manifestEditor.json.title",title:"Form ⇄ JSON",contentKey:"tutorial.manifestEditor.json.content",content:"Each section can be edited as a visual form or as raw JSON — use the toggle inside the section.",placement:"auto"}],Ge=[];function We(t){return t}const Ye=u.forwardRef(function(o,a){var F;const{value:r,defaultValue:s,sections:i=Ge,onChange:n,jsonView:d=!0,scriptRunner:f,triggers:y,bindings:g=[],handlers:l,onBindingsChange:p,revisions:T,onRollback:O,loadContent:$,logs:M,onClearLogs:I,extraTabs:_,validate:A,theme:P="light",height:D=560,tutorial:C,className:N,style:w,id:V,"data-testid":z}=o,{t:K}=c.useNiceTranslation(),[k,J]=c.useControllableState({value:r,defaultValue:s,fallbackValue:{},onChange:n,componentName:"NiceManifestEditor"}),j=u.useMemo(()=>{const q=i.map(U=>({key:`section:${U.id}`,label:U.title,icon:U.icon,content:e.jsx("div",{className:"nice-manifest-editor__pane",children:e.jsx(X,{schema:U.schema,fields:U.fields,uiSchema:U.uiSchema,value:k,onChange:J,showJsonView:d})})}));return f&&q.push({key:"scripts",label:K("manifestEditor.tab.scripts","Scripts"),content:e.jsx("div",{className:"nice-manifest-editor__pane",children:e.jsx(c.NiceScriptRunner,{...f})})}),y&&y.length>0&&q.push({key:"lifecycle",label:K("manifestEditor.tab.lifecycle","Lifecycle"),content:e.jsx("div",{className:"nice-manifest-editor__pane",children:e.jsx(c.NiceLifecycleHooksEditor,{triggers:y,bindings:g,handlers:l,onChange:U=>p==null?void 0:p(U),groupByTrigger:!0,allowCondition:!0})})}),T&&T.length>0&&q.push({key:"history",label:K("manifestEditor.tab.history","History"),content:e.jsx("div",{className:"nice-manifest-editor__pane",children:e.jsx(c.NiceRevisionHistory,{revisions:T,onRollback:O,loadContent:$,language:"json"})})}),_&&q.push(..._),q},[i,k,J,d,f,y,g,l,p,T,O,$,_,K]),[R,h]=u.useState(((F=j[0])==null?void 0:F.key)??"");u.useEffect(()=>{j.length>0&&!j.some(q=>q.key===R)&&h(j[0].key)},[j,R]);const x=u.useMemo(()=>A?A(k):[],[A,k]),E=u.useMemo(()=>{const q=[{key:"sections",label:`${i.length} ${K("manifestEditor.sections","sections")}`,position:"left"}];return A&&q.push({key:"validation",label:e.jsxs("span",{className:"nice-manifest-editor__status",children:[e.jsx(c.NiceIcon,{name:x.length===0?"check":"warning",size:12}),x.length===0?K("manifestEditor.status.valid","Valid"):`${x.length} ${K("manifestEditor.status.issues","issues")}`]}),position:"left"}),q},[i.length,A,x.length,K]),b="nice-manifest-editor"+(N?` ${N}`:"");return e.jsx(c.NiceConsole,{ref:a,id:V,className:b,style:{height:D,...w},"data-testid":z,theme:P,tabs:j,activeTabKey:R,onTabChange:h,statusItems:E,toolbar:C?e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(C,He)}):void 0,bottomPanel:M!==void 0?e.jsx(c.NiceLogConsole,{title:K("manifestEditor.output","Output"),entries:M,onClear:I,maxHeight:"100%"}):void 0})}),te="__eeRid",ie="__eeFid",Qe=[{target:".nice-entity-editor",titleKey:"tutorial.entityEditor.intro.title",title:"Entity editor",contentKey:"tutorial.entityEditor.intro.content",content:"Browse your entities in the list, then click one (or “New entity”) to edit its metadata, fields and validation on a dedicated screen.",placement:"auto"}],Xe={type:"object",properties:{name:{type:"string",title:"Name",minLength:1,description:"Unique technical name of the entity (PascalCase)."},displayName:{type:"string",title:"Display name",description:"Human-friendly name shown in the UI."},tableName:{type:"string",title:"Table name",description:"Database table that backs this entity."},description:{type:"string",title:"Description",description:"Optional notes about the entity's purpose."},entityIcon:{type:"string",title:"Icon",description:"Icon key shown next to the entity."},isAudited:{type:"boolean",title:"Audited",description:"Track who created/changed each record and when."},isSoftDeleteEnabled:{type:"boolean",title:"Soft delete",description:"Flag rows as deleted instead of physically removing them."}},required:["name"]},Ze={type:"object",properties:{name:{type:"string",title:"Name",minLength:1,description:"Field's technical name (the database column)."},displayName:{type:"string",title:"Display name",description:"Human-friendly label shown in the UI."},dataType:{type:"string",title:"Type",description:"Storage / data type of the field.",enum:["Guid","string","text","int","long","decimal","double","bool","DateTime","DateOnly","json"]},isPrimaryKey:{type:"boolean",title:"Primary key",description:"Primary key — uniquely identifies each record."},isForeignKey:{type:"boolean",title:"Foreign key",description:"Foreign key — references another entity's primary key."},isRequired:{type:"boolean",title:"Required",description:"Value must be provided (NOT NULL)."},isUnique:{type:"boolean",title:"Unique",description:"Each value must be unique across all records."},isIndexed:{type:"boolean",title:"Indexed",description:"Add a database index for faster lookups and filtering."},isNullable:{type:"boolean",title:"Nullable",description:"Allow empty (NULL) values."},maxLength:{type:"integer",title:"Max length",description:"Maximum number of characters (for string types)."},defaultValue:{type:"string",title:"Default",description:"Value used when none is provided."},description:{type:"string",title:"Description",description:"Optional notes about the field."},isComputed:{type:"boolean",title:"Computed",description:"Value is derived from an expression instead of stored input."},computedExpression:{type:"string",title:"Computed expression",description:"Expression used to compute the value (when Computed is on)."}},required:["name","dataType"]};function ne({title:t,help:o}){return e.jsxs("span",{className:"nice-entity-editor__field-label",children:[t,o?e.jsx(c.NiceTooltip,{content:o,children:e.jsx("span",{className:"nice-entity-editor__help",role:"img","aria-label":o,children:e.jsx(c.NiceIcon,{name:"info",size:14})})}):null]})}function et({schema:t,value:o,onChange:a,readOnly:r}){const s=t.properties??{};return e.jsx("div",{className:"nice-entity-editor__field-form",children:Object.entries(s).map(([i,n])=>{const d=o[i],f=n.description,y=n.title??i;if(n.type==="boolean")return e.jsx("div",{className:"nice-entity-editor__field-row nice-entity-editor__field-row--check",children:e.jsx(c.NiceCheckbox,{label:e.jsx(ne,{title:y,help:f}),checked:!!d,onChange:l=>a(i,l),disabled:r})},i);if(Array.isArray(n.enum)&&n.enum.length>0)return e.jsxs("div",{className:"nice-entity-editor__field-row",children:[e.jsx(ne,{title:y,help:f}),e.jsx(c.NiceSelect,{options:n.enum.map(l=>({label:String(l),value:String(l)})),value:d==null?"":String(d),onChange:l=>a(i,l),clearable:!0,disabled:r})]},i);const g=n.type==="integer"||n.type==="number";return e.jsxs("div",{className:"nice-entity-editor__field-row",children:[e.jsx(ne,{title:y,help:f}),e.jsx(c.NiceTextInput,{value:d==null?"":String(d),onChange:l=>a(i,g?l===""?void 0:Number(l):l),disabled:r})]},i)})})}function tt({fields:t,onChange:o,fieldSchema:a,readOnly:r}){const{t:s}=c.useNiceTranslation(),[i,n]=u.useState(null),d=u.useMemo(()=>t.map((l,p)=>({...l,[ie]:String(p)})),[t]),f=u.useMemo(()=>[{field:"name",header:s("entityEditor.field.name","Name"),sortable:!0,render:l=>e.jsx("span",{className:"nice-entity-editor__name",children:String(l??"")})},{field:"dataType",header:s("entityEditor.field.type","Type"),sortable:!0,render:l=>e.jsx(c.NiceBadge,{variant:"secondary",size:"sm",outline:!0,children:String(l??"—")})},{field:"__flags",header:s("entityEditor.field.flags","Constraints"),headerTooltip:s("entityEditor.field.flags.help","Key / required / unique / indexed constraints on this field"),render:(l,p)=>{const T=[[!!(p!=null&&p.isPrimaryKey),"PK",s("entityEditor.flag.pk","Primary key"),"info"],[!!(p!=null&&p.isForeignKey),"FK",s("entityEditor.flag.fk","Foreign key"),"info"],[!!(p!=null&&p.isRequired),"Req",s("entityEditor.flag.required","Required (NOT NULL)"),"warning"],[!!(p!=null&&p.isUnique),"Uniq",s("entityEditor.flag.unique","Unique"),"secondary"],[!!(p!=null&&p.isIndexed),"Idx",s("entityEditor.flag.indexed","Indexed"),"secondary"]];return e.jsx("span",{className:"nice-entity-editor__flags",children:T.filter(([O])=>O).map(([,O,$,M])=>e.jsx(c.NiceTooltip,{content:$,children:e.jsx(c.NiceBadge,{variant:M,size:"sm",children:O})},O))})}}],[]),y=(l,p,T)=>{o(t.map((O,$)=>$===l?{...O,[p]:T}:O))},g=()=>{const l=[...t,{name:`field${t.length+1}`,dataType:"string"}];o(l),n(l.length-1)};if(i!=null&&t[i]){const l=t[i];return e.jsxs("div",{className:"nice-entity-editor__field-detail",children:[e.jsxs("header",{className:"nice-entity-editor__edit-header",children:[e.jsx(c.NiceTooltip,{content:s("entityEditor.field.backHint","Back to the field list"),children:e.jsx(c.NiceButton,{variant:"ghost",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"arrow-left",size:14}),onClick:()=>n(null),children:s("entityEditor.field.back","Fields")})}),e.jsx("span",{className:"nice-entity-editor__breadcrumb-sep",children:"/"}),e.jsx("span",{className:"nice-entity-editor__edit-title",children:String(l.name??s("entityEditor.field.untitled","New field"))})]}),e.jsx(et,{schema:a,value:l,onChange:(p,T)=>y(i,p,T),readOnly:r}),e.jsx("div",{className:"nice-entity-editor__field-detail-actions",children:e.jsx(c.NiceButton,{variant:"primary",size:"sm",onClick:()=>n(null),children:s("entityEditor.field.done","Done")})})]})}return e.jsx(c.NiceDataGrid,{data:d,keyField:ie,columns:f,searchable:!0,searchPlaceholder:s("entityEditor.field.search","Search fields…"),emptyText:s("entityEditor.field.empty","No fields yet. Add one to define this entity."),onRowClick:l=>n(Number(l[ie])),onRowDelete:r?void 0:l=>o(t.filter((p,T)=>T!==Number(l))),toolbar:r?void 0:e.jsx(c.NiceButton,{variant:"primary",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:g,children:s("entityEditor.field.add","Add field")}),compact:!0,striped:!0})}const pe=u.forwardRef(function(o,a){const{value:r,defaultValue:s,onChange:i,entityMetaSchema:n=Xe,fieldSchema:d=Ze,fieldsKey:f="fields",validationsKey:y="validations",nameKey:g="name",renderErPreview:l,readOnly:p=!1,tutorial:T,className:O,style:$,id:M,"data-testid":I}=o,{t:_}=c.useNiceTranslation(),[A,P]=c.useControllableState({value:r,defaultValue:s,fallbackValue:[],onChange:i,componentName:"NiceEntityEditor"}),[D,C]=u.useState("list"),[N,w]=u.useState(0),[V,z]=u.useState("general"),K=Math.min(N,Math.max(0,A.length-1)),k=A[K],J=D==="edit"&&k!=null,j=u.useMemo(()=>{const S=k==null?void 0:k[f];return Array.isArray(S)?S:[]},[k,f]),R=u.useMemo(()=>{const S=B=>{const G=B.toLowerCase();return/(int|long|decimal|double|float|number|money)/.test(G)?"number":/bool/.test(G)?"boolean":/date|time/.test(G)?"date":"string"},L=[];for(const B of j){const G=String(B.name??"");G&&L.push({field:G,label:String(B.displayName??G),type:S(String(B.dataType??"string"))})}return L},[j]),h=u.useMemo(()=>{const S=k==null?void 0:k[y];return Array.isArray(S)?S:[]},[k,y]),x=u.useMemo(()=>A.map((S,L)=>({...S,[te]:String(L)})),[A]),E=S=>{P(A.map((L,B)=>B===K?{...L,...S}:L))},b=S=>{E({[f]:S})},F=S=>{w(S),z("general"),C("edit")},q=()=>{const S=[...A,{[g]:`Entity${A.length+1}`,[f]:[]}];P(S),w(S.length-1),z("general"),C("edit")},U=S=>{P(A.filter((L,B)=>B!==S)),w(L=>L>=S?Math.max(0,L-1):L)},Z=u.useMemo(()=>[{field:g,header:_("entityEditor.col.name","Name"),sortable:!0,render:S=>e.jsx("span",{className:"nice-entity-editor__name",children:String(S??"")})},{field:"displayName",header:_("entityEditor.col.displayName","Display name"),sortable:!0,render:S=>e.jsx("span",{className:"nice-entity-editor__muted",children:String(S??"—")})},{field:"tableName",header:_("entityEditor.col.table","Table"),sortable:!0,render:S=>e.jsx("span",{className:"nice-entity-editor__muted",children:String(S??"—")})},{field:f,header:_("entityEditor.col.fields","Fields"),align:"center",headerTooltip:_("entityEditor.col.fields.help","Number of fields defined on this entity"),render:S=>e.jsx(c.NiceBadge,{variant:"secondary",size:"sm",children:Array.isArray(S)?S.length:0})},{field:"__flags",header:_("entityEditor.col.flags","Flags"),render:(S,L)=>e.jsxs("span",{className:"nice-entity-editor__flags",children:[L!=null&&L.isAudited?e.jsx(c.NiceTooltip,{content:_("entityEditor.flag.audited","Audited — tracks who changed each record and when"),children:e.jsx(c.NiceBadge,{variant:"info",size:"sm",outline:!0,children:_("entityEditor.flag.audited.abbr","Audit")})}):null,L!=null&&L.isSoftDeleteEnabled?e.jsx(c.NiceTooltip,{content:_("entityEditor.flag.softDelete","Soft delete — rows are flagged deleted, never physically removed"),children:e.jsx(c.NiceBadge,{variant:"secondary",size:"sm",outline:!0,children:_("entityEditor.flag.softDelete.abbr","Soft-del")})}):null]})}],[g,f]),H=u.useMemo(()=>{const S=[{id:"general",label:_("entityEditor.tab.general","General"),content:k?e.jsx(X,{schema:n,value:k,onChange:L=>E(L),columns:2,readOnly:p,liveValidation:!0}):null},{id:"fields",label:_("entityEditor.tab.fields","Fields"),badge:j.length||void 0,content:e.jsx(tt,{fields:j,onChange:b,fieldSchema:d,readOnly:p})},{id:"validation",label:_("entityEditor.tab.validation","Validation"),badge:h.length||void 0,content:e.jsx(c.NiceValidationBuilder,{fields:R,value:h,onChange:L=>E({[y]:L})})}];return l&&S.push({id:"er",label:_("entityEditor.tab.er","ER diagram"),content:e.jsx("div",{className:"nice-entity-editor__er",children:l(A)})}),S},[k,j,h,R,n,d,p,l,A]),Y="nice-entity-editor"+(O?` ${O}`:"");return e.jsxs("div",{ref:a,id:M,className:Y,style:$,"data-testid":I,children:[T&&e.jsx("div",{className:"nice-entity-editor__tutorial",children:e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(T,Qe)})}),J?e.jsxs("div",{className:"nice-entity-editor__edit",children:[e.jsxs("header",{className:"nice-entity-editor__edit-header",children:[e.jsx(c.NiceTooltip,{content:_("entityEditor.backHint","Back to the entity list"),children:e.jsx(c.NiceButton,{variant:"ghost",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"arrow-left",size:14}),onClick:()=>C("list"),children:_("entityEditor.back","Entities")})}),e.jsx("span",{className:"nice-entity-editor__breadcrumb-sep",children:"/"}),e.jsx("span",{className:"nice-entity-editor__edit-title",children:String((k==null?void 0:k[g])??_("entityEditor.untitled","Untitled entity"))}),!p&&e.jsx(c.NiceTooltip,{content:_("entityEditor.deleteHint","Delete this entity"),children:e.jsx(c.NiceButton,{variant:"ghost",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"trash",size:14}),onClick:()=>{U(K),C("list")},children:_("entityEditor.delete","Delete")})})]}),e.jsx(c.NiceTabs,{tabs:H,activeTab:V,onChange:z,variant:"enclosed"})]}):e.jsx("div",{className:"nice-entity-editor__list-view",children:e.jsx(c.NiceDataGrid,{data:x,keyField:te,columns:Z,searchable:!0,searchPlaceholder:_("entityEditor.search","Search entities…"),emptyText:_("entityEditor.empty","No entities yet. Create one to get started."),onRowClick:S=>F(Number(S[te])),onRowDelete:p?void 0:S=>U(Number(S)),toolbar:p?void 0:e.jsx(c.NiceButton,{variant:"primary",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:q,children:_("entityEditor.new","New entity")}),compact:!0,striped:!0})})]})}),it=[{target:".nice-i18n-editor",titleKey:"tutorial.i18nEditor.intro.title",title:"Translations",contentKey:"tutorial.i18nEditor.intro.content",content:"Edit translations as a keys × locales grid. Add keys and locales; amber cells mark missing translations.",placement:"auto"},{target:'[data-tour="i18n-grid"]',titleKey:"tutorial.i18nEditor.grid.title",title:"Keys × locales",contentKey:"tutorial.i18nEditor.grid.content",content:"Each row is a translation key and each column a locale. Edit a cell to set a translation; amber cells are still missing.",placement:"top"},{target:'[data-tour="i18n-add"]',titleKey:"tutorial.i18nEditor.add.title",title:"Add keys & locales",contentKey:"tutorial.i18nEditor.add.content",content:"Add a new translation key or a new locale column here; new cells start empty and are flagged as missing.",placement:"top"}],he=u.forwardRef(function(o,a){const{value:r,defaultValue:s,onChange:i,locales:n,allowEditLocales:d=!0,allowEditKeys:f=!0,highlightMissing:y=!0,readOnly:g=!1,tutorial:l,className:p,style:T,id:O,"data-testid":$}=o,{t:M}=W.useNiceTranslation(),[I,_]=W.useControllableState({value:r,defaultValue:s,fallbackValue:{},onChange:i,componentName:"NiceI18nEditor"}),[A,P]=u.useState(""),[D,C]=u.useState(""),N=u.useMemo(()=>n??Object.keys(I),[n,I]),w=u.useMemo(()=>{const h=new Set;for(const x of Object.keys(I))for(const E of Object.keys(I[x]??{}))h.add(E);return[...h].sort()},[I]),V=(h,x,E)=>{_({...I,[h]:{...I[h]??{},[x]:E}})},z=(h,x)=>{if(!x||x===h)return;const E={};for(const b of Object.keys(I)){const F={...I[b]??{}};h in F&&(F[x]=F[h],delete F[h]),E[b]=F}_(E)},K=h=>{const x={};for(const E of Object.keys(I)){const b={...I[E]??{}};delete b[h],x[E]=b}_(x)},k=()=>{const h=A.trim();if(!h||w.includes(h))return;const x={};for(const E of N)x[E]={...I[E]??{},[h]:""};for(const E of Object.keys(I))x[E]||(x[E]=I[E]);_(x),P("")},J=()=>{const h=D.trim();if(!h||I[h])return;const x={};for(const E of w)x[E]="";_({...I,[h]:x}),C("")},j=h=>{const x={...I};delete x[h],_(x)},R="nice-i18n-editor"+(p?` ${p}`:"");return e.jsxs("div",{ref:a,id:O,className:R,style:T,"data-testid":$,children:[l&&e.jsx("div",{className:"nice-i18n-editor__tutorial",children:e.jsx(W.NiceTutorialButton,{steps:W.resolveTutorial(l,it)})}),e.jsx("div",{className:"nice-i18n-editor__scroll","data-tour":"i18n-grid",children:e.jsxs("table",{className:"nice-i18n-editor__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"nice-i18n-editor__key-head",children:M("i18nEditor.keyHead","Key")}),N.map(h=>e.jsxs("th",{className:"nice-i18n-editor__locale-head",children:[e.jsx("span",{children:h}),d&&!g&&e.jsx("button",{type:"button",className:"nice-i18n-editor__locale-remove","aria-label":`${M("i18nEditor.removeLocale","Remove locale")} ${h}`,onClick:()=>j(h),children:e.jsx(W.NiceIcon,{name:"close",size:12})})]},h))]})}),e.jsxs("tbody",{children:[w.map(h=>e.jsxs("tr",{children:[e.jsxs("td",{className:"nice-i18n-editor__key-cell",children:[f&&!g?e.jsx("input",{className:"nice-i18n-editor__key-input",defaultValue:h,onBlur:x=>z(h,x.target.value.trim()),"aria-label":M("i18nEditor.keyAria","Translation key")}):e.jsx("span",{className:"nice-i18n-editor__key-text",children:h}),f&&!g&&e.jsx("button",{type:"button",className:"nice-i18n-editor__key-remove","aria-label":`${M("i18nEditor.removeKey","Remove key")} ${h}`,onClick:()=>K(h),children:e.jsx(W.NiceIcon,{name:"close",size:12})})]}),N.map(x=>{var F;const E=((F=I[x])==null?void 0:F[h])??"",b=y&&E==="";return e.jsx("td",{className:"nice-i18n-editor__cell",children:e.jsx("input",{className:"nice-i18n-editor__cell-input"+(b?" nice-i18n-editor__cell-input--missing":""),value:E,readOnly:g,onChange:q=>V(x,h,q.target.value),"aria-label":`${h} (${x})`})},x)})]},h)),w.length===0&&e.jsx("tr",{children:e.jsx("td",{className:"nice-i18n-editor__empty",colSpan:N.length+1,children:M("i18nEditor.empty","No translation keys yet.")})})]})]})}),!g&&(f||d)&&e.jsxs("div",{className:"nice-i18n-editor__toolbar","data-tour":"i18n-add",children:[f&&e.jsxs("div",{className:"nice-i18n-editor__add",children:[e.jsx("input",{className:"nice-i18n-editor__add-input",placeholder:M("i18nEditor.newKeyPlaceholder","new.key"),value:A,onChange:h=>P(h.target.value),onKeyDown:h=>{h.key==="Enter"&&k()},"aria-label":M("i18nEditor.newKeyAria","New key")}),e.jsxs("button",{type:"button",onClick:k,children:["+ ",M("i18nEditor.addKey","Key")]})]}),d&&e.jsxs("div",{className:"nice-i18n-editor__add",children:[e.jsx("input",{className:"nice-i18n-editor__add-input",placeholder:M("i18nEditor.newLocalePlaceholder","locale (e.g. de)"),value:D,onChange:h=>C(h.target.value),onKeyDown:h=>{h.key==="Enter"&&J()},"aria-label":M("i18nEditor.newLocaleAria","New locale")}),e.jsxs("button",{type:"button",onClick:J,children:["+ ",M("i18nEditor.addLocale","Locale")]})]})]})]})}),nt=[{target:".nice-module-editor",titleKey:"tutorial.moduleEditor.intro.title",title:"Module editor",contentKey:"tutorial.moduleEditor.intro.content",content:"Design a whole module end-to-end — manifest, entities, translations, views, workflows, data sources and permissions — then validate and save.",placement:"auto"},{target:'[data-tour="nme-browser"]',titleKey:"tutorial.moduleEditor.browser.title",title:"Module browser",contentKey:"tutorial.moduleEditor.browser.content",content:"Search and pick a module here to open its manifest, entities and translations.",placement:"right"},{target:'[data-tour="nme-tabs"]',titleKey:"tutorial.moduleEditor.tabs.title",title:"Module parts",contentKey:"tutorial.moduleEditor.tabs.content",content:"Each tab edits one part of the module: Manifest sections, Entities, i18n, Views, Workflows, Data sources, Permissions and more.",placement:"bottom"},{target:'[data-tour="nme-validate"]',titleKey:"tutorial.moduleEditor.validate.title",title:"Validate",contentKey:"tutorial.moduleEditor.validate.content",content:"Check the module against the manifest schema. Issues appear in the status bar and the output panel.",placement:"bottom"},{target:'[data-tour="nme-save"]',titleKey:"tutorial.moduleEditor.save.title",title:"Save",contentKey:"tutorial.moduleEditor.save.content",content:"Persist your changes through the configured data provider (e.g. write the files back to disk).",placement:"bottom"},{target:'[data-tour="nme-output"]',titleKey:"tutorial.moduleEditor.output.title",title:"Output",contentKey:"tutorial.moduleEditor.output.content",content:"Validation results and load/save activity are logged here.",placement:"top"}],at=[],st=u.forwardRef(function(o,a){var le;const{dataProvider:r,manifestSections:s=at,entityConfig:i,locales:n,validate:d,scriptRunner:f,triggers:y,bindings:g=[],handlers:l,onBindingsChange:p,revisions:T,onRollback:O,loadContent:$,theme:M="light",height:I=640,tutorial:_,className:A,style:P,id:D,"data-testid":C}=o,{t:N}=c.useNiceTranslation(),[w,V]=u.useState([]),[z,K]=u.useState(""),[k,J]=u.useState(null),[j,R]=u.useState(null),[h,x]=u.useState(!1),[E,b]=u.useState(!1),[F,q]=u.useState([]),[U,Z]=u.useState(""),H=u.useCallback((m,v,ke)=>{q(Se=>[...Se,{level:m,message:v,data:ke,timestamp:Date.now()}].slice(-200))},[]),Y=u.useCallback(async()=>{b(!0);try{V(await r.listModules())}catch(m){H("error",`List modules failed: ${m instanceof Error?m.message:String(m)}`)}finally{b(!1)}},[r,H]);u.useEffect(()=>{Y()},[Y]);const S=u.useCallback(async m=>{b(!0);try{const v=await r.loadModule(m);R(v),J(m),x(!1),H("info",`Loaded module ${m}`)}catch(v){H("error",`Load failed: ${v instanceof Error?v.message:String(v)}`)}finally{b(!1)}},[r,H]),L=u.useCallback(async()=>{if(!(!k||!j)){b(!0);try{await r.saveModule(k,j),x(!1),H("info",`Saved module ${k}`)}catch(m){H("error",`Save failed: ${m instanceof Error?m.message:String(m)}`)}finally{b(!1)}}},[k,j,r,H]),B=u.useMemo(()=>{if(!j)return[];const m=[];for(const v of s)v.schema&&m.push(...oe(j.manifest??{},v.schema));return d&&m.push(...d(j)),m},[j,s,d]),G=u.useCallback(()=>{if(B.length===0)H("info","Validation passed");else{H("warn",`${B.length} validation issue(s)`);for(const m of B)H("error",`${m.field}: ${m.message}`)}},[B,H]),fe=m=>{R(v=>v&&{...v,manifest:m}),x(!0)},ye=m=>{R(v=>v&&{...v,entities:m}),x(!0)},ge=m=>{R(v=>v&&{...v,i18n:m}),x(!0)},be=m=>{R(v=>v&&{...v,views:m}),x(!0)},ve=m=>{R(v=>v&&{...v,workflows:m}),x(!0)},Ne=m=>{R(v=>v&&{...v,dataSources:m}),x(!0)},xe=m=>{R(v=>v&&{...v,rbac:m}),x(!0)},Q=u.useMemo(()=>{if(!j)return[];const m=s.map(v=>({key:`section:${v.id}`,label:v.title,icon:v.icon,content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(X,{schema:v.schema,fields:v.fields,uiSchema:v.uiSchema,value:j.manifest??{},onChange:fe,showJsonView:!0})})}));return m.push({key:"entities",label:N("moduleEditor.tab.entities","Entities"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(pe,{value:j.entities??[],onChange:ye,entityMetaSchema:i==null?void 0:i.entityMetaSchema,fieldSchema:i==null?void 0:i.fieldSchema,fieldsKey:i==null?void 0:i.fieldsKey,nameKey:i==null?void 0:i.nameKey,renderErPreview:i==null?void 0:i.renderErPreview})})}),m.push({key:"i18n",label:N("moduleEditor.tab.i18n","i18n"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(he,{value:j.i18n??{},onChange:ge,locales:n})})}),m.push({key:"views",label:N("moduleEditor.tab.views","Views"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(ot,{views:j.views??[],entities:j.entities??[],onChange:be})})}),m.push({key:"workflows",label:N("moduleEditor.tab.workflows","Workflows"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(rt,{workflows:j.workflows??[],onChange:ve})})}),m.push({key:"data",label:N("moduleEditor.tab.data","Data"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(dt,{dataSources:j.dataSources??[],schemas:lt(j.entities??[]),onChange:Ne})})}),m.push({key:"permissions",label:N("moduleEditor.tab.permissions","Permissions"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(c.NiceAccessManager,{value:j.rbac??ct(j),onChange:xe})})}),f&&m.push({key:"scripts",label:N("moduleEditor.tab.scripts","Scripts"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(c.NiceScriptRunner,{...f})})}),y&&y.length>0&&m.push({key:"lifecycle",label:N("moduleEditor.tab.lifecycle","Lifecycle"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(c.NiceLifecycleHooksEditor,{triggers:y,bindings:g,handlers:l,onChange:v=>p==null?void 0:p(v),groupByTrigger:!0,allowCondition:!0})})}),T&&T.length>0&&m.push({key:"history",label:N("moduleEditor.tab.history","History"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx(c.NiceRevisionHistory,{revisions:T,onRollback:O,loadContent:$,language:"json"})})}),m.push({key:"source",label:N("moduleEditor.tab.source","Source"),content:e.jsx("div",{className:"nice-module-editor__pane",children:e.jsx("pre",{className:"nice-module-editor__source",children:JSON.stringify(j,null,2)})})}),m},[j,s,i,n,f,y,g,l,T,N]);u.useEffect(()=>{Q.length>0&&!Q.some(m=>m.key===U)&&Z(Q[0].key)},[Q,U]);const re=u.useMemo(()=>{const m=z.trim().toLowerCase();return m?w.filter(v=>v.id.toLowerCase().includes(m)||(v.name??"").toLowerCase().includes(m)||(v.category??"").toLowerCase().includes(m)):w},[w,z]),_e=u.useMemo(()=>{const m=[];return k&&m.push({key:"mod",label:k+(h?" •":""),position:"left"}),m.push({key:"val",label:e.jsxs("span",{className:"nice-module-editor__status",children:[e.jsx(c.NiceIcon,{name:B.length===0?"check":"warning",size:12}),B.length===0?N("moduleEditor.status.valid","Valid"):`${B.length} ${N("moduleEditor.status.issues","issues")}`]}),position:"left"}),m},[k,h,B.length,N]),je=e.jsxs("div",{className:"nice-module-editor__browser","data-tour":"nme-browser",children:[e.jsx("input",{className:"nice-module-editor__search",placeholder:N("moduleEditor.searchModules","Search modules…"),value:z,onChange:m=>K(m.target.value),"aria-label":N("moduleEditor.searchModules","Search modules…")}),e.jsxs("div",{className:"nice-module-editor__modules",children:[re.map(m=>e.jsxs("button",{type:"button",className:"nice-module-editor__module"+(m.id===k?" nice-module-editor__module--active":""),onClick:()=>void S(m.id),title:m.description,children:[e.jsx("span",{className:"nice-module-editor__module-name",children:m.name??m.id}),m.category&&e.jsx("span",{className:"nice-module-editor__module-cat",children:m.category})]},m.id)),re.length===0&&e.jsx("div",{className:"nice-module-editor__browser-empty",children:E?N("moduleEditor.loading","Loading…"):N("moduleEditor.noModules","No modules. Open a source first.")})]})]}),Ee=e.jsxs("div",{className:"nice-module-editor__toolbar",children:[e.jsx("strong",{className:"nice-module-editor__title","data-tour":"nme-tabs",children:k?((le=j==null?void 0:j.manifest)==null?void 0:le.packageName)??k:N("moduleEditor.title","Module Editor")}),_&&e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(_,nt)}),e.jsx("span",{className:"nice-module-editor__spacer"}),e.jsxs("button",{type:"button",onClick:()=>void Y(),disabled:E,children:[e.jsx(c.NiceIcon,{name:"refresh",size:14})," ",N("moduleEditor.refresh","Refresh")]}),e.jsxs("button",{type:"button","data-tour":"nme-validate",onClick:G,disabled:!j,children:[e.jsx(c.NiceIcon,{name:"check",size:14})," ",N("moduleEditor.validate","Validate")]}),e.jsx("button",{type:"button","data-tour":"nme-save",className:"nice-module-editor__save",onClick:()=>void L(),disabled:!j||!h||E,children:E?N("moduleEditor.saving","Saving…"):N("moduleEditor.save","Save")})]}),we="nice-module-editor"+(A?` ${A}`:"");return e.jsx(c.NiceConsole,{ref:a,id:D,className:we,style:{height:I,...P},"data-testid":C,theme:M,tabs:Q,activeTabKey:U,onTabChange:Z,toolbar:Ee,sidePanel:je,sidePanelWidth:260,statusItems:_e,bottomPanel:e.jsx("div",{"data-tour":"nme-output",style:{height:"100%"},children:e.jsx(c.NiceLogConsole,{title:N("moduleEditor.output","Output"),entries:F,onClear:()=>q([]),maxHeight:"100%"})}),children:!j&&e.jsx("div",{className:"nice-module-editor__placeholder",children:N("moduleEditor.placeholder","Select a module from the left to start editing.")})})});function ot({views:t,entities:o,onChange:a}){var g;const{t:r}=c.useNiceTranslation(),[s,i]=u.useState(((g=t[0])==null?void 0:g.id)??null),n=t.find(l=>l.id===s)??null,d=l=>{a(t.map(p=>p.id===s?l:p)),l.id!==s&&i(l.id)},f=()=>{const l={id:`view-${Date.now().toString(36)}`,name:"New View",version:2,columns:12,rows:[],dataSources:[]};a([...t,l]),i(l.id)},y=l=>{a(t.filter(p=>p.id!==l)),s===l&&i(null)};return e.jsxs("div",{className:"nice-module-views",children:[e.jsxs("div",{className:"nice-module-views__bar",children:[e.jsxs("select",{className:"nice-module-views__select",value:s??"",onChange:l=>i(l.target.value||null),"aria-label":r("moduleEditor.views.select","Select view"),children:[e.jsx("option",{value:"",children:r("moduleEditor.views.placeholder","— select view —")}),t.map(l=>e.jsx("option",{value:l.id,children:l.name},l.id))]}),e.jsxs("button",{type:"button",onClick:f,children:["+ ",r("moduleEditor.views.new","New view")]}),n&&e.jsx("button",{type:"button",onClick:()=>y(n.id),children:r("moduleEditor.delete","Delete")})]}),n?e.jsx(c.NiceViewEditor,{value:n,onChange:d,entities:o,height:520}):e.jsx("div",{className:"nice-module-views__empty",children:r("moduleEditor.views.empty","No view selected. Create one, then use “New from entity” inside the editor.")})]})}function rt({workflows:t,onChange:o}){var y;const{t:a}=c.useNiceTranslation(),[r,s]=u.useState(((y=t[0])==null?void 0:y.id)??null),i=t.find(g=>g.id===r)??null,n=g=>{o(t.map(l=>l.id===r?g:l)),g.id!==r&&s(g.id)},d=()=>{const g={id:`workflow-${Date.now().toString(36)}`,name:"New Workflow",entityType:"",version:1,states:[],transitions:[]};o([...t,g]),s(g.id)},f=g=>{o(t.filter(l=>l.id!==g)),r===g&&s(null)};return e.jsxs("div",{className:"nice-module-views",children:[e.jsxs("div",{className:"nice-module-views__bar",children:[e.jsxs("select",{className:"nice-module-views__select",value:r??"",onChange:g=>s(g.target.value||null),"aria-label":a("moduleEditor.workflows.select","Select workflow"),children:[e.jsx("option",{value:"",children:a("moduleEditor.workflows.placeholder","— select workflow —")}),t.map(g=>e.jsx("option",{value:g.id,children:g.name},g.id))]}),e.jsxs("button",{type:"button",onClick:d,children:["+ ",a("moduleEditor.workflows.new","New workflow")]}),i&&e.jsx("button",{type:"button",onClick:()=>f(i.id),children:a("moduleEditor.delete","Delete")})]}),i?e.jsx(c.NiceWorkflowDesigner,{workflow:i,onChange:n}):e.jsx("div",{className:"nice-module-views__empty",children:a("moduleEditor.workflows.empty","No workflow selected. Create one to start designing states and transitions.")})]})}function lt(t){return t.map(o=>{const a=o;return{name:String(a.tableName||a.name||"Entity"),columns:(Array.isArray(a.fields)?a.fields:[]).map(r=>({name:String(r.name??""),dataType:String(r.dataType??"string"),isPrimaryKey:!!r.isPrimaryKey,isForeignKey:!!r.isForeignKey}))}})}function ct(t){const o=t.manifest??{},a=String(o.displayName||o.packageName||"Module"),r=(t.views??[]).map(i=>({id:`view:${i.id}`,label:i.name,type:"view"})),s=(t.entities??[]).map(i=>{const n=String(i.name??"Entity");return{id:`entity:${n}`,label:n,type:"entity"}});return{roles:[{id:"admin",label:"Admin"},{id:"user",label:"User"}],actions:[{id:"view",label:"View"},{id:"create",label:"Create"},{id:"edit",label:"Edit"},{id:"delete",label:"Delete"}],resources:[{id:"module",label:a,type:"module",children:[...r.length?[{id:"views",label:"Views",type:"group",children:r}]:[],...s.length?[{id:"entities",label:"Entities",type:"group",children:s}]:[]]}],grants:{}}}function dt({dataSources:t,schemas:o,onChange:a}){var g;const{t:r}=c.useNiceTranslation(),[s,i]=u.useState(((g=t[0])==null?void 0:g.key)??null),n=t.find(l=>l.key===s)??null,d=l=>{a(t.map(p=>p.key===s?l:p)),l.key!==s&&i(l.key)},f=()=>{const l={key:`ds-${Date.now().toString(36)}`,kind:"query",query:{tables:[],joins:[],conditions:[],sorts:[],groupBy:[],distinct:!1},sql:""};a([...t,l]),i(l.key)},y=l=>{a(t.filter(p=>p.key!==l)),s===l&&i(null)};return e.jsxs("div",{className:"nice-module-views",children:[e.jsxs("div",{className:"nice-module-views__bar",children:[e.jsxs("select",{className:"nice-module-views__select",value:s??"",onChange:l=>i(l.target.value||null),"aria-label":r("moduleEditor.data.select","Select data source"),children:[e.jsx("option",{value:"",children:r("moduleEditor.data.placeholder","— select data source —")}),t.map(l=>e.jsx("option",{value:l.key,children:l.label||l.key},l.key))]}),e.jsxs("button",{type:"button",onClick:f,children:["+ ",r("moduleEditor.data.new","New data source")]}),n&&e.jsx("button",{type:"button",onClick:()=>y(n.key),children:r("moduleEditor.delete","Delete")})]}),n?e.jsx(c.NiceDataSourceBuilder,{value:n,onChange:d,schemas:o}):e.jsx("div",{className:"nice-module-views__empty",children:r("moduleEditor.data.empty","No data source selected. Create one to build a query from your module’s schema.")})]})}exports.NiceArrayField=me;exports.NiceEntityEditor=pe;exports.NiceFormBuilderAI=Be;exports.NiceI18nEditor=he;exports.NiceManifestEditor=Ye;exports.NiceModuleEditor=st;exports.NiceSchemaForm=X;exports.defineManifestSection=We;exports.formBuilderSchemaToNiceFormItems=Fe;exports.formFieldsToFormItems=se;exports.formSchemaToJsonSchema=Ue;exports.jsonSchemaToFormItems=ae;exports.schemaToFormItems=Ie;exports.validateAgainstJsonSchema=oe;exports.validateFormSchema=Ce;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),ue=require("@nice2dev/ui-core"),g=require("react"),c=require("@nice2dev/ui"),P=require("./studio.cjs");function We(t){var r,u;const a={text:"text",email:"email",password:"password",phone:"phone",url:"url",textarea:"textarea",number:"number",date:"date",datetime:"datetime",time:"time",select:"select",multiselect:"tags",checkbox:"checkbox",toggle:"toggle",radio:"radio",slider:"slider",rating:"rating",color:"color",file:"file",image:"file"},o=[];for(const i of t.sections)for(const s of i.fields)s.type==="heading"||s.type==="paragraph"||s.type==="divider"||s.type==="spacer"||s.type==="section"||o.push({field:s.name,label:s.label||s.name,type:a[s.type]||"text",placeholder:s.placeholder,hint:s.helpText,defaultValue:s.defaultValue,required:s.required||((r=s.validations)==null?void 0:r.some(l=>l.type==="required")),disabled:s.disabled,readOnly:s.readonly,group:i.title,options:(u=s.options)==null?void 0:u.map(l=>typeof l=="string"?{label:l,value:l}:{label:l.label,value:l.value})});return o}function Ee(t){var o;const a={text:"NiceTextInput",textarea:"NiceTextArea",number:"NiceNumberInput",email:"NiceTextInput",password:"NicePasswordInput",date:"NiceDateTimePicker",datetime:"NiceDateTimePicker",time:"NiceDateTimePicker",select:"NiceSelect",multiselect:"NiceTagBox",checkbox:"NiceCheckbox",toggle:"NiceToggle",radio:"NiceRadioGroup",slider:"NiceSlider",rating:"NiceRating",color:"NiceColorPicker"};return{dataField:t.name,label:{text:t.label},editorType:a[t.type]||"NiceTextInput",editorOptions:{placeholder:t.placeholder,disabled:t.disabled,readOnly:t.readonly,...t.props},colSpan:Math.ceil((t.colSpan||12)/6),validationRules:(o=t.validations)==null?void 0:o.map(r=>({type:r.type,message:r.message,...r.value!==void 0?{[r.type]:r.value}:{}})),helpText:t.helpText}}function Je(t){const a=[];for(const o of t.sections)o.title?a.push({itemType:"group",caption:o.title,colCount:o.columns||2,items:o.fields.map(Ee)}):a.push(...o.fields.map(Ee));return a}function Ue(t){const a=[];t.version||a.push("Missing schema version"),t.id||a.push("Missing form ID"),(!t.sections||t.sections.length===0)&&a.push("Form must have at least one section");const o=new Set;for(const r of t.sections||[])for(const u of r.fields||[])u.id||a.push(`Field missing ID: ${u.name}`),u.name||a.push(`Field missing name: ${u.id}`),o.has(u.name)&&a.push(`Duplicate field name: ${u.name}`),o.add(u.name);return{valid:a.length===0,errors:a}}const Ge={text:"text",string:"text",textarea:"textarea",number:"number",integer:"number",email:"email",password:"password",phone:"phone",tel:"phone",url:"url",date:"date",datetime:"datetime",time:"time",select:"select",dropdown:"select",multiselect:"multiselect",checkbox:"checkbox",boolean:"checkbox",toggle:"toggle",switch:"toggle",radio:"radio",slider:"slider",range:"slider",rating:"rating",stars:"rating",color:"color",file:"file",upload:"file",signature:"signature",richtext:"richtext",markdown:"markdown"};function Ke(t){return Ge[String(t??"").toLowerCase()]??"text"}function He(t){return(Array.isArray(t)?t:t.fields).map((o,r)=>{const u=o.name??o.field??o.id??`field${r+1}`,i=o.validation??{},s=[],l=(n,m)=>{m!==void 0&&s.push({type:n,value:m,...i.message?{message:i.message}:{}})};return l("min",i.min),l("max",i.max),l("minLength",i.minLength),l("maxLength",i.maxLength),l("pattern",i.pattern),{id:o.id??u,name:u,type:Ke(o.type),...o.label!==void 0?{label:o.label}:{},...o.placeholder!==void 0?{placeholder:o.placeholder}:{},...o.helpText!==void 0?{helpText:o.helpText}:{},...o.defaultValue!==void 0?{defaultValue:o.defaultValue}:{},...o.required?{required:!0}:{},...o.options?{options:[...o.options]}:{},...s.length?{validations:s}:{}}})}const Ye={text:{type:"string"},textarea:{type:"string"},password:{type:"string",format:"password"},phone:{type:"string",format:"phone"},url:{type:"string",format:"uri"},email:{type:"string",format:"email"},date:{type:"string",format:"date"},datetime:{type:"string",format:"date-time"},time:{type:"string",format:"time"},color:{type:"string",format:"color"},number:{type:"number"},slider:{type:"number"},rating:{type:"integer"},checkbox:{type:"boolean"},toggle:{type:"boolean"},select:{type:"string"},radio:{type:"string"},multiselect:{type:"array",items:{type:"string"}},file:{type:"string",format:"data-url"},signature:{type:"string",format:"data-url"},richtext:{type:"string"},markdown:{type:"string"},code:{type:"string"},image:{type:"string",format:"uri"}};function Xe(t,a){if(a)for(const o of a)switch(o.type){case"minLength":typeof o.value=="number"&&(t.minLength=o.value);break;case"maxLength":typeof o.value=="number"&&(t.maxLength=o.value);break;case"min":typeof o.value=="number"&&(t.minimum=o.value);break;case"max":typeof o.value=="number"&&(t.maximum=o.value);break;case"pattern":typeof o.value=="string"&&(t.pattern=o.value);break;case"email":t.format="email";break;case"url":t.format="uri";break}}function Qe(t){if(t.type==="heading"||t.type==="paragraph"||t.type==="divider"||t.type==="spacer")return null;const a=Ye[t.type];if(!a)return null;const o={...a};return t.label&&(o.title=t.label),t.helpText&&(o.description=t.helpText),t.defaultValue!==void 0&&(o.default=t.defaultValue),t.options&&(t.type==="select"||t.type==="radio")&&(o.enum=t.options.map(r=>typeof r=="string"?r:r.value)),t.options&&t.type==="multiselect"&&(o.items={type:"string",enum:t.options.map(r=>typeof r=="string"?r:String(r.value))}),Xe(o,t.validations),o}function Ze(t){const a={},o=[],r=i=>{var s;for(const l of i){if(l.type==="section"&&l.children){r(l.children);continue}const n=Qe(l);n&&(a[l.name]=n,(l.required||(s=l.validations)!=null&&s.some(m=>m.type==="required"))&&o.push(l.name))}};for(const i of t.sections)r(i.fields);const u={$schema:"http://json-schema.org/draft-07/schema#",$id:t.id,type:"object",title:t.title,description:t.description,properties:a,additionalProperties:!1};return o.length>0&&(u.required=o),u}function Me(t){const{t:a}=ue.useNiceTranslation(),{value:o,onChange:r,readOnly:u}=t,[i,s]=g.useState(()=>{try{return o===void 0?"":JSON.stringify(o,null,2)}catch{return""}}),[l,n]=g.useState(null);return g.useEffect(()=>{try{s(o===void 0?"":JSON.stringify(o,null,2))}catch{}},[JSON.stringify(o)]),e.jsxs("div",{className:"nice-schema-form__json-field",children:[e.jsx("textarea",{className:"nice-schema-form__json-textarea",value:i,readOnly:u,spellCheck:!1,rows:Math.min(12,Math.max(3,i.split(`
2
+ `).length)),onChange:m=>{const d=m.target.value;s(d);const p=d.trim();if(p===""){n(null),r(void 0);return}try{r(JSON.parse(p)),n(null)}catch(v){n(v instanceof Error?v.message:a("jsonSchemaToFormItems.invalidJson","Invalid JSON"))}}}),l&&e.jsx("div",{className:"nice-schema-form__json-error",children:l})]})}function et(t){switch(t){case"email":return"email";case"uri":case"url":return"url";case"date":return"date";case"date-time":return"datetime";case"time":return"time";case"color":return"color";case"password":return"password";case"phone":return"phone";case"data-url":return"file";default:return"text"}}function tt(t,a,o,r={}){const u={field:t,label:a.title??t,required:o,hint:a.description,defaultValue:a.default};if(a.enum&&a.enum.length>0)return{...u,type:"select",options:a.enum.map(i=>({label:String(i),value:i}))};switch(a.type){case"number":case"integer":return{...u,type:"number"};case"boolean":return{...u,type:"checkbox"};case"string":return{...u,type:et(a.format)};case"array":{const i=a.items;if(i!=null&&i.enum&&i.enum.length>0)return{...u,type:"tags",options:i.enum.map(s=>({label:String(s),value:String(s)}))};if((i==null?void 0:i.type)==="object"&&i.properties&&r.renderArrayField){const s=r.renderArrayField;return{...u,render:(l,n)=>s(l??[],n,i,u.label)}}return(i==null?void 0:i.type)==="string"||(i==null?void 0:i.type)==="number"||(i==null?void 0:i.type)==="integer"?{...u,type:"tags"}:{...u,render:(s,l)=>e.jsx(Me,{value:s,onChange:l})}}case"object":if(r.renderObjectField){const i=r.renderObjectField;return{...u,render:(s,l)=>i(s??{},l,a,u.label)}}return{...u,render:(i,s)=>e.jsx(Me,{value:i,onChange:s})};default:return{...u,type:"text"}}}function we(t,a={}){const{uiSchema:o,renderArrayField:r,renderObjectField:u}=a,i={renderArrayField:r,renderObjectField:u},s=t.properties??{},l=new Set(t.required??[]);return Object.keys(s).map(n=>{const m=tt(n,s[n],l.has(n),i);return o!=null&&o[n]?{...m,...o[n]}:m})}const it={text:"text",textarea:"textarea",number:"number",email:"email",password:"password",phone:"phone",url:"url",date:"date",datetime:"datetime",time:"time",select:"select",multiselect:"tags",checkbox:"checkbox",toggle:"toggle",radio:"radio",slider:"slider",rating:"rating",color:"color"};function _e(t,a={}){var u,i;const{uiSchema:o}=a,r=[];for(const s of t){if(s.type==="section"&&s.children){for(const m of _e(s.children,a))r.push(s.label?{...m,group:s.label}:m);continue}const l=it[s.type];if(!l)continue;const n={field:s.name,label:s.label,type:l,required:s.required||((u=s.validations)==null?void 0:u.some(m=>m.type==="required")),placeholder:s.placeholder,hint:s.helpText,defaultValue:s.defaultValue,disabled:s.disabled,readOnly:s.readonly,options:(i=s.options)==null?void 0:i.map(m=>typeof m=="string"?{label:m,value:m}:{label:m.label,value:m.value})};r.push(o!=null&&o[s.name]?{...n,...o[s.name]}:n)}return r}function $e(t){return t==null||t===""||Array.isArray(t)&&t.length===0}function Ie(t,a){const o=[],r=a.properties??{},u=new Set(a.required??[]);for(const i of Object.keys(r)){const s=r[i],l=t[i];if(u.has(i)&&$e(l)){o.push({field:i,message:`${s.title??i} is required`});continue}if(!$e(l)&&(s.enum&&!s.enum.includes(l)&&o.push({field:i,message:`${s.title??i} must be one of: ${s.enum.join(", ")}`}),(s.type==="number"||s.type==="integer")&&typeof l=="number"&&(s.minimum!==void 0&&l<s.minimum&&o.push({field:i,message:`${s.title??i} must be ≥ ${s.minimum}`}),s.maximum!==void 0&&l>s.maximum&&o.push({field:i,message:`${s.title??i} must be ≤ ${s.maximum}`})),s.type==="string"&&typeof l=="string"&&(s.minLength!==void 0&&l.length<s.minLength&&o.push({field:i,message:`${s.title??i} must be at least ${s.minLength} chars`}),s.maxLength!==void 0&&l.length>s.maxLength&&o.push({field:i,message:`${s.title??i} must be at most ${s.maxLength} chars`}),s.pattern)))try{new RegExp(s.pattern).test(l)||o.push({field:i,message:`${s.title??i} has an invalid format`})}catch{}}return o}const be="__nafRid";function nt(t){return Array.isArray(t)?`[${t.length}]`:t&&typeof t=="object"?"{…}":t==null?"":String(t)}const Be=g.forwardRef(function(a,o){const{value:r,defaultValue:u,onChange:i,itemSchema:s,title:l,readOnly:n=!1,columns:m,className:d,style:p,"data-testid":v}=a,[k,w]=c.useControllableState({value:r,defaultValue:u,fallbackValue:[],onChange:i,componentName:"NiceArrayField"}),A=s.properties??{},R=g.useMemo(()=>(m??Object.keys(A)).map(E=>{const h=A[E]??{},y={field:E,header:h.title??E};return h.type==="boolean"?(y.render=S=>S?e.jsx(c.NiceIcon,{name:"check",size:14,title:"true"}):"",y.align="center"):(h.type==="array"||h.type==="object")&&(y.render=S=>nt(S)),y}),[s,m]),L=g.useMemo(()=>we(s),[s]),j=g.useMemo(()=>k.map((b,E)=>({...b,[be]:String(E)})),[k]),$=b=>{const{[be]:E,...h}=b;return h},M="nice-array-field"+(d?` ${d}`:"");return e.jsx("div",{ref:o,className:M,style:p,"data-testid":v,children:e.jsx(c.NiceDataGrid,{data:j,keyField:be,columns:R,editMode:"popup",formItems:L,editFormTitle:l?`${l} — item`:"Edit item",emptyText:`No items${l?` in ${l}`:""}`,compact:!0,onRowAdd:n?void 0:b=>w([...k,$(b)]),onRowEdit:n?void 0:(b,E)=>{const h=Number(b);w(k.map((y,S)=>S===h?$(E):y))},onRowDelete:n?void 0:b=>{const E=Number(b);w(k.filter((h,y)=>y!==E))}})})}),st=[{target:".nice-schema-form",titleKey:"tutorial.schemaForm.intro.title",title:"Schema form",contentKey:"tutorial.schemaForm.intro.content",content:"This form is generated from a schema. Required fields and validation errors are flagged; use the JSON toggle for raw editing.",placement:"auto"},{target:'[data-tour="sf-viewtoggle"]',titleKey:"tutorial.schemaForm.viewToggle.title",title:"Form ⇄ JSON",contentKey:"tutorial.schemaForm.viewToggle.content",content:"Switch between the visual form and the raw JSON value — handy for power users and copy/paste.",placement:"bottom"},{target:".nice-schema-form",titleKey:"tutorial.schemaForm.validation.title",title:"Live validation",contentKey:"tutorial.schemaForm.validation.content",content:"Values are validated against the schema as you type; any problems are listed below the form.",placement:"auto"}];function at(t){const a=[],o=r=>{for(const u of r){if(u.type==="section"&&u.children){o(u.children);continue}u.required&&a.push({id:`${u.name}-required`,field:u.name,op:"required"});for(const i of u.validations??[])a.push({id:`${u.name}-${i.type}`,field:u.name,op:i.type,value:typeof i.value=="boolean"?void 0:i.value,message:i.message??(i.type==="required"?`${u.label??u.name} is required`:void 0)})}};return o(t),a}function ot(t,a){return c.evaluateValidation(at(t),a).filter(o=>o.severity==="error").map(o=>({field:o.field,message:o.message}))}const pe=g.forwardRef(function(a,o){const{schema:r,fields:u,uiSchema:i,value:s,defaultValue:l,onChange:n,onValidate:m,showJsonView:d=!1,columns:p=1,labelPosition:v="top",readOnly:k=!1,liveValidation:w=!0,validationRules:A,tutorial:R,className:L,style:j,id:$,"data-testid":M}=a,{t:b}=c.useNiceTranslation(),[E,h]=c.useControllableState({value:s,defaultValue:l,fallbackValue:{},onChange:n,componentName:"NiceSchemaForm"}),[y,S]=g.useState(!1),[O,V]=g.useState(""),[N,J]=g.useState(null),X=g.useMemo(()=>r?we(r,{uiSchema:i,renderArrayField:(F,H,G,ee)=>e.jsx(Be,{value:F,onChange:H,itemSchema:G,title:ee,readOnly:k})}):u?_e(u,{uiSchema:i}):[],[r,u,i,k]),Q=g.useMemo(()=>{const F=r?Ie(E,r):u?ot(u,E):[];if(A!=null&&A.length){const H=c.evaluateValidation(A,E).filter(G=>G.severity==="error").map(G=>({field:G.field,message:G.message}));return[...F,...H]}return F},[r,u,E,A]);g.useEffect(()=>{m==null||m(Q)},[Q,m]),g.useEffect(()=>{if(y)try{V(JSON.stringify(E,null,2)),J(null)}catch{}},[y,E]);const K=(F,H)=>{h({...E,[F]:H})},T="nice-schema-form"+(L?` ${L}`:"");return e.jsxs("div",{ref:o,id:$,className:T,style:j,"data-testid":M,children:[R&&e.jsx("div",{className:"nice-schema-form__tutorial",children:e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(R,st)})}),d&&e.jsxs("div",{className:"nice-schema-form__toolbar","data-tour":"sf-viewtoggle",children:[e.jsx("button",{type:"button",className:"nice-schema-form__tab"+(y?"":" nice-schema-form__tab--active"),onClick:()=>S(!1),children:b("schemaForm.tab.form","Form")}),e.jsx(c.NiceTooltip,{content:b("schemaForm.tab.json.help","Edit the raw JSON value directly"),children:e.jsx("button",{type:"button",className:"nice-schema-form__tab"+(y?" nice-schema-form__tab--active":""),onClick:()=>S(!0),children:b("schemaForm.tab.json","JSON")})})]}),y?e.jsxs("div",{className:"nice-schema-form__json",children:[e.jsx("textarea",{className:"nice-schema-form__json-textarea",value:O,readOnly:k,spellCheck:!1,rows:Math.min(24,Math.max(6,O.split(`
3
+ `).length)),onChange:F=>{const H=F.target.value;V(H);try{const G=JSON.parse(H);J(null),h(G)}catch(G){J(G instanceof Error?G.message:b("schemaForm.invalidJson","Invalid JSON"))}}}),N&&e.jsx("div",{className:"nice-schema-form__json-error",children:N})]}):e.jsx(c.NiceForm,{items:X,data:E,onFieldChange:K,columns:p,labelPosition:v,readOnly:k}),w&&Q.length>0&&e.jsx("ul",{className:"nice-schema-form__errors",role:"alert",children:Q.map((F,H)=>e.jsx("li",{className:"nice-schema-form__error",children:F.message},`${F.field}-${H}`))})]})}),ke="__eeRid",je="__eeFid",lt=[{target:".nice-entity-editor",titleKey:"tutorial.entityEditor.intro.title",title:"Entity editor",contentKey:"tutorial.entityEditor.intro.content",content:"Browse your entities in the list, then click one (or “New entity”) to edit its metadata, fields and validation on a dedicated screen.",placement:"auto"}],dt={type:"object",properties:{name:{type:"string",title:"Name",minLength:1,description:"Unique technical name of the entity (PascalCase)."},displayName:{type:"string",title:"Display name",description:"Human-friendly name shown in the UI."},tableName:{type:"string",title:"Table name",description:"Database table that backs this entity."},description:{type:"string",title:"Description",description:"Optional notes about the entity's purpose."},entityIcon:{type:"string",title:"Icon",description:"Icon key shown next to the entity."},isAudited:{type:"boolean",title:"Audited",description:"Track who created/changed each record and when."},isSoftDeleteEnabled:{type:"boolean",title:"Soft delete",description:"Flag rows as deleted instead of physically removing them."}},required:["name"]},rt={type:"object",properties:{name:{type:"string",title:"Name",minLength:1,description:"Field's technical name (the database column)."},displayName:{type:"string",title:"Display name",description:"Human-friendly label shown in the UI."},dataType:{type:"string",title:"Type",description:"Storage / data type of the field.",enum:["Guid","string","text","int","long","decimal","double","bool","DateTime","DateOnly","json"]},isPrimaryKey:{type:"boolean",title:"Primary key",description:"Primary key — uniquely identifies each record."},isForeignKey:{type:"boolean",title:"Foreign key",description:"Foreign key — references another entity's primary key."},isRequired:{type:"boolean",title:"Required",description:"Value must be provided (NOT NULL)."},isUnique:{type:"boolean",title:"Unique",description:"Each value must be unique across all records."},isIndexed:{type:"boolean",title:"Indexed",description:"Add a database index for faster lookups and filtering."},isNullable:{type:"boolean",title:"Nullable",description:"Allow empty (NULL) values."},maxLength:{type:"integer",title:"Max length",description:"Maximum number of characters (for string types)."},defaultValue:{type:"string",title:"Default",description:"Value used when none is provided."},description:{type:"string",title:"Description",description:"Optional notes about the field."},isComputed:{type:"boolean",title:"Computed",description:"Value is derived from an expression instead of stored input."},computedExpression:{type:"string",title:"Computed expression",description:"Expression used to compute the value (when Computed is on)."}},required:["name","dataType"]};function Ne({title:t,help:a}){return e.jsxs("span",{className:"nice-entity-editor__field-label",children:[t,a?e.jsx(c.NiceTooltip,{content:a,children:e.jsx("span",{className:"nice-entity-editor__help",role:"img","aria-label":a,children:e.jsx(c.NiceIcon,{name:"info",size:14})})}):null]})}function ct({schema:t,value:a,onChange:o,readOnly:r}){const u=t.properties??{};return e.jsx("div",{className:"nice-entity-editor__field-form",children:Object.entries(u).map(([i,s])=>{const l=a[i],n=s.description,m=s.title??i;if(s.type==="boolean")return e.jsx("div",{className:"nice-entity-editor__field-row nice-entity-editor__field-row--check",children:e.jsx(c.NiceCheckbox,{label:e.jsx(Ne,{title:m,help:n}),checked:!!l,onChange:p=>o(i,p),disabled:r})},i);if(Array.isArray(s.enum)&&s.enum.length>0)return e.jsxs("div",{className:"nice-entity-editor__field-row",children:[e.jsx(Ne,{title:m,help:n}),e.jsx(c.NiceSelect,{options:s.enum.map(p=>({label:String(p),value:String(p)})),value:l==null?"":String(l),onChange:p=>o(i,p),clearable:!0,disabled:r})]},i);const d=s.type==="integer"||s.type==="number";return e.jsxs("div",{className:"nice-entity-editor__field-row",children:[e.jsx(Ne,{title:m,help:n}),e.jsx(c.NiceTextInput,{value:l==null?"":String(l),onChange:p=>o(i,d?p===""?void 0:Number(p):p),disabled:r})]},i)})})}function ut({fields:t,onChange:a,fieldSchema:o,readOnly:r}){const{t:u}=c.useNiceTranslation(),[i,s]=g.useState(null),l=g.useMemo(()=>t.map((p,v)=>({...p,[je]:String(v)})),[t]),n=g.useMemo(()=>[{field:"name",header:u("entityEditor.field.name","Name"),sortable:!0,render:p=>e.jsx("span",{className:"nice-entity-editor__name",children:String(p??"")})},{field:"dataType",header:u("entityEditor.field.type","Type"),sortable:!0,render:p=>e.jsx(c.NiceBadge,{variant:"secondary",size:"sm",outline:!0,children:String(p??"—")})},{field:"__flags",header:u("entityEditor.field.flags","Constraints"),headerTooltip:u("entityEditor.field.flags.help","Key / required / unique / indexed constraints on this field"),render:(p,v)=>{const k=[[!!(v!=null&&v.isPrimaryKey),"PK",u("entityEditor.flag.pk","Primary key"),"info"],[!!(v!=null&&v.isForeignKey),"FK",u("entityEditor.flag.fk","Foreign key"),"info"],[!!(v!=null&&v.isRequired),"Req",u("entityEditor.flag.required","Required (NOT NULL)"),"warning"],[!!(v!=null&&v.isUnique),"Uniq",u("entityEditor.flag.unique","Unique"),"secondary"],[!!(v!=null&&v.isIndexed),"Idx",u("entityEditor.flag.indexed","Indexed"),"secondary"]];return e.jsx("span",{className:"nice-entity-editor__flags",children:k.filter(([w])=>w).map(([,w,A,R])=>e.jsx(c.NiceTooltip,{content:A,children:e.jsx(c.NiceBadge,{variant:R,size:"sm",children:w})},w))})}}],[]),m=(p,v,k)=>{a(t.map((w,A)=>A===p?{...w,[v]:k}:w))},d=()=>{const p=[...t,{name:`field${t.length+1}`,dataType:"string"}];a(p),s(p.length-1)};if(i!=null&&t[i]){const p=t[i];return e.jsxs("div",{className:"nice-entity-editor__field-detail",children:[e.jsxs("header",{className:"nice-entity-editor__edit-header",children:[e.jsx(c.NiceTooltip,{content:u("entityEditor.field.backHint","Back to the field list"),children:e.jsx(c.NiceButton,{variant:"ghost",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"arrow-left",size:14}),onClick:()=>s(null),children:u("entityEditor.field.back","Fields")})}),e.jsx("span",{className:"nice-entity-editor__breadcrumb-sep",children:"/"}),e.jsx("span",{className:"nice-entity-editor__edit-title",children:String(p.name??u("entityEditor.field.untitled","New field"))})]}),e.jsx(ct,{schema:o,value:p,onChange:(v,k)=>m(i,v,k),readOnly:r}),e.jsx("div",{className:"nice-entity-editor__field-detail-actions",children:e.jsx(c.NiceButton,{variant:"primary",size:"sm",onClick:()=>s(null),children:u("entityEditor.field.done","Done")})})]})}return e.jsx(c.NiceDataGrid,{data:l,keyField:je,columns:n,searchable:!0,searchPlaceholder:u("entityEditor.field.search","Search fields…"),emptyText:u("entityEditor.field.empty","No fields yet. Add one to define this entity."),onRowClick:p=>s(Number(p[je])),onRowDelete:r?void 0:p=>a(t.filter((v,k)=>k!==Number(p))),toolbar:r?void 0:e.jsx(c.NiceButton,{variant:"primary",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:d,children:u("entityEditor.field.add","Add field")}),compact:!0,striped:!0})}const Te=g.forwardRef(function(a,o){const{value:r,defaultValue:u,onChange:i,entityMetaSchema:s=dt,fieldSchema:l=rt,fieldsKey:n="fields",validationsKey:m="validations",nameKey:d="name",renderErPreview:p,readOnly:v=!1,tutorial:k,className:w,style:A,id:R,"data-testid":L}=a,{t:j}=c.useNiceTranslation(),[$,M]=c.useControllableState({value:r,defaultValue:u,fallbackValue:[],onChange:i,componentName:"NiceEntityEditor"}),[b,E]=g.useState("list"),[h,y]=g.useState(0),[S,O]=g.useState("general"),V=Math.min(h,Math.max(0,$.length-1)),N=$[V],J=b==="edit"&&N!=null,X=g.useMemo(()=>{const x=N==null?void 0:N[n];return Array.isArray(x)?x:[]},[N,n]),Q=g.useMemo(()=>{const x=B=>{const q=B.toLowerCase();return/(int|long|decimal|double|float|number|money)/.test(q)?"number":/bool/.test(q)?"boolean":/date|time/.test(q)?"date":"string"},C=[];for(const B of X){const q=String(B.name??"");q&&C.push({field:q,label:String(B.displayName??q),type:x(String(B.dataType??"string"))})}return C},[X]),K=g.useMemo(()=>{const x=N==null?void 0:N[m];return Array.isArray(x)?x:[]},[N,m]),T=g.useMemo(()=>$.map((x,C)=>({...x,[ke]:String(C)})),[$]),F=x=>{M($.map((C,B)=>B===V?{...C,...x}:C))},H=x=>{F({[n]:x})},G=x=>{y(x),O("general"),E("edit")},ee=()=>{const x=[...$,{[d]:`Entity${$.length+1}`,[n]:[]}];M(x),y(x.length-1),O("general"),E("edit")},te=x=>{M($.filter((C,B)=>B!==x)),y(C=>C>=x?Math.max(0,C-1):C)},ae=g.useMemo(()=>[{field:d,header:j("entityEditor.col.name","Name"),sortable:!0,render:x=>e.jsx("span",{className:"nice-entity-editor__name",children:String(x??"")})},{field:"displayName",header:j("entityEditor.col.displayName","Display name"),sortable:!0,render:x=>e.jsx("span",{className:"nice-entity-editor__muted",children:String(x??"—")})},{field:"tableName",header:j("entityEditor.col.table","Table"),sortable:!0,render:x=>e.jsx("span",{className:"nice-entity-editor__muted",children:String(x??"—")})},{field:n,header:j("entityEditor.col.fields","Fields"),align:"center",headerTooltip:j("entityEditor.col.fields.help","Number of fields defined on this entity"),render:x=>e.jsx(c.NiceBadge,{variant:"secondary",size:"sm",children:Array.isArray(x)?x.length:0})},{field:"__flags",header:j("entityEditor.col.flags","Flags"),render:(x,C)=>e.jsxs("span",{className:"nice-entity-editor__flags",children:[C!=null&&C.isAudited?e.jsx(c.NiceTooltip,{content:j("entityEditor.flag.audited","Audited — tracks who changed each record and when"),children:e.jsx(c.NiceBadge,{variant:"info",size:"sm",outline:!0,children:j("entityEditor.flag.audited.abbr","Audit")})}):null,C!=null&&C.isSoftDeleteEnabled?e.jsx(c.NiceTooltip,{content:j("entityEditor.flag.softDelete","Soft delete — rows are flagged deleted, never physically removed"),children:e.jsx(c.NiceBadge,{variant:"secondary",size:"sm",outline:!0,children:j("entityEditor.flag.softDelete.abbr","Soft-del")})}):null]})}],[d,n]),_=g.useMemo(()=>{const x=[{id:"general",label:j("entityEditor.tab.general","General"),content:N?e.jsx(pe,{schema:s,value:N,onChange:C=>F(C),columns:2,readOnly:v,liveValidation:!0}):null},{id:"fields",label:j("entityEditor.tab.fields","Fields"),badge:X.length||void 0,content:e.jsx(ut,{fields:X,onChange:H,fieldSchema:l,readOnly:v})},{id:"validation",label:j("entityEditor.tab.validation","Validation"),badge:K.length||void 0,content:e.jsx(c.NiceValidationBuilder,{fields:Q,value:K,onChange:C=>F({[m]:C})})}];return p&&x.push({id:"er",label:j("entityEditor.tab.er","ER diagram"),content:e.jsx("div",{className:"nice-entity-editor__er",children:p($)})}),x},[N,X,K,Q,s,l,v,p,$]),I="nice-entity-editor"+(w?` ${w}`:"");return e.jsxs("div",{ref:o,id:R,className:I,style:A,"data-testid":L,children:[k&&e.jsx("div",{className:"nice-entity-editor__tutorial",children:e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(k,lt)})}),J?e.jsxs("div",{className:"nice-entity-editor__edit",children:[e.jsxs("header",{className:"nice-entity-editor__edit-header",children:[e.jsx(c.NiceTooltip,{content:j("entityEditor.backHint","Back to the entity list"),children:e.jsx(c.NiceButton,{variant:"ghost",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"arrow-left",size:14}),onClick:()=>E("list"),children:j("entityEditor.back","Entities")})}),e.jsx("span",{className:"nice-entity-editor__breadcrumb-sep",children:"/"}),e.jsx("span",{className:"nice-entity-editor__edit-title",children:String((N==null?void 0:N[d])??j("entityEditor.untitled","Untitled entity"))}),!v&&e.jsx(c.NiceTooltip,{content:j("entityEditor.deleteHint","Delete this entity"),children:e.jsx(c.NiceButton,{variant:"ghost",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"trash",size:14}),onClick:()=>{te(V),E("list")},children:j("entityEditor.delete","Delete")})})]}),e.jsx(c.NiceTabs,{tabs:_,activeTab:S,onChange:O,variant:"enclosed"})]}):e.jsx("div",{className:"nice-entity-editor__list-view",children:e.jsx(c.NiceDataGrid,{data:T,keyField:ke,columns:ae,searchable:!0,searchPlaceholder:j("entityEditor.search","Search entities…"),emptyText:j("entityEditor.empty","No entities yet. Create one to get started."),onRowClick:x=>G(Number(x[ke])),onRowDelete:v?void 0:x=>te(Number(x)),toolbar:v?void 0:e.jsx(c.NiceButton,{variant:"primary",size:"sm",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:ee,children:j("entityEditor.new","New entity")}),compact:!0,striped:!0})})]})}),mt=4e6;function pt(t,a){const o=t.split(/\r?\n/),r=a.split(/\r?\n/);if(o.length*r.length>mt)return[...o.map(d=>({type:"remove",text:d})),...r.map(d=>({type:"add",text:d}))];const u=o.length,i=r.length,s=Array.from({length:u+1},()=>new Uint32Array(i+1));for(let d=u-1;d>=0;d--)for(let p=i-1;p>=0;p--)s[d][p]=o[d]===r[p]?s[d+1][p+1]+1:Math.max(s[d+1][p],s[d][p+1]);const l=[];let n=0,m=0;for(;n<u&&m<i;)o[n]===r[m]?(l.push({type:"same",text:o[n]}),n++,m++):s[n+1][m]>=s[n][m+1]?l.push({type:"remove",text:o[n++]}):l.push({type:"add",text:r[m++]});for(;n<u;)l.push({type:"remove",text:o[n++]});for(;m<i;)l.push({type:"add",text:r[m++]});return l}function De({before:t,after:a,context:o=3}){const{t:r}=c.useNiceTranslation(),u=g.useMemo(()=>{const i=pt(t,a),s=new Set;i.forEach((m,d)=>{if(m.type!=="same")for(let p=Math.max(0,d-o);p<=Math.min(i.length-1,d+o);p++)s.add(p)});const l=[];let n=0;return i.forEach((m,d)=>{s.has(d)?(n>0&&(l.push({type:"gap",count:n}),n=0),l.push(m)):n++}),n>0&&l.length>0&&l.push({type:"gap",count:n}),l},[t,a,o]);return u.length===0?e.jsx("p",{className:"nice-development-studio__muted",children:r("devStudio.diff.none","No changes.")}):e.jsx("pre",{className:"nice-development-studio__diff","aria-label":r("devStudio.diff.label","Changes"),children:u.map((i,s)=>i.type==="gap"?e.jsxs("span",{className:"nice-development-studio__diff-gap",children:[r("devStudio.diff.unchanged","{count} unchanged lines").replace("{count}",String(i.count)),`
4
+ `]},s):e.jsxs("span",{className:`nice-development-studio__diff-line nice-development-studio__diff-line--${i.type}`,children:[i.type==="add"?"+ ":i.type==="remove"?"- ":" ",i.text,`
5
+ `]},s))})}function ht({open:t,onClose:a,session:o,preset:r,locales:u,prefill:i,onCreated:s}){var $,M,b,E;const{t:l}=c.useNiceTranslation(),n=o.workspaces.filter(h=>!h.readOnly),m=r.requiredLocales??[],[d,p]=g.useState(()=>{var h;return{workspaceId:i.workspaceId&&n.some(y=>y.id===i.workspaceId)?i.workspaceId:((h=n[0])==null?void 0:h.id)??"",packageId:i.packageId,name:"",entities:[{name:"Item",fields:[{name:"Id",dataType:"Guid",isPrimaryKey:!0,isRequired:!0},{name:"Name",dataType:"string",isRequired:!0,maxLength:200}]}],locales:[...new Set([...m,...u.slice(0,2)])],views:!0,permissions:!0}}),[v,k]=g.useState(null),[w,A]=g.useState(!1),R=g.useMemo(()=>[...new Set((o.modulesByWs[d.workspaceId]??[]).map(h=>h.packageId).filter(Boolean))].sort(),[o.modulesByWs,d.workspaceId]);if(!t)return null;const L=new Set(Object.values(o.modulesByWs).flatMap(h=>h.map(y=>y.id))),j=async()=>{r.generateModule&&d.name.trim()&&k(await r.generateModule({...d,name:d.name.trim()},{existingIds:L}))};return e.jsx(c.NiceModal,{open:t,onClose:a,title:l("devStudio.wizard.title","New module"),size:"xl","data-testid":"studio-module-wizard",children:e.jsx(c.NiceWizard,{finishLabel:l("devStudio.wizard.create","Create module"),onCancel:a,onStepChange:h=>{h===3&&j()},onComplete:async()=>{if(w)return;A(!0);const h=await o.createModule({...d,name:d.name.trim()});A(!1),h&&(s({workspaceId:h.workspaceId,id:h.id}),a())},steps:[{id:"identity",title:l("devStudio.wizard.identity","Name and place"),validate:()=>d.name.trim()&&d.workspaceId?!0:l("devStudio.wizard.needName","Give the module a name."),content:e.jsxs("div",{className:"nice-development-studio__form",children:[e.jsx(c.NiceSelect,{label:l("devStudio.wizard.workspace","Project"),value:d.workspaceId,options:n.map(h=>({value:h.id,label:h.label})),onChange:h=>p({...d,workspaceId:String(h)})}),e.jsx(c.NiceTextInput,{label:l("devStudio.wizard.package","Package"),value:d.packageId??"",placeholder:R.join(", "),onChange:h=>p({...d,packageId:h||void 0})}),e.jsx(c.NiceTextInput,{label:l("devStudio.wizard.name","Name"),value:d.name,placeholder:l("devStudio.wizard.namePlaceholder","e.g. Bike rental"),onChange:h=>p({...d,name:h})}),e.jsx(c.NiceTextInput,{label:l("devStudio.wizard.description","Description"),value:d.description??"",onChange:h=>p({...d,description:h||void 0})})]})},{id:"entities",title:l("devStudio.wizard.entities","Entities"),content:e.jsx(Te,{value:d.entities,onChange:h=>p({...d,entities:h}),entityMetaSchema:($=r.entities)==null?void 0:$.entityMetaSchema,fieldSchema:(M=r.entities)==null?void 0:M.fieldSchema,fieldsKey:(b=r.entities)==null?void 0:b.fieldsKey,nameKey:(E=r.entities)==null?void 0:E.nameKey})},{id:"options",title:l("devStudio.wizard.options","Options"),content:e.jsxs("div",{className:"nice-development-studio__form",children:[e.jsxs("fieldset",{className:"nice-development-studio__fieldset",children:[e.jsx("legend",{children:l("devStudio.wizard.locales","Languages")}),[...new Set([...m,...u])].map(h=>e.jsx(c.NiceCheckbox,{label:h,checked:d.locales.includes(h),disabled:m.includes(h),onChange:y=>p({...d,locales:y?[...d.locales,h]:d.locales.filter(S=>S!==h)})},h))]}),e.jsx(c.NiceCheckbox,{label:l("devStudio.wizard.views","A list and a form view per entity"),checked:!!d.views,onChange:h=>p({...d,views:h})}),e.jsx(c.NiceCheckbox,{label:l("devStudio.wizard.permissions","Viewer, editor and admin permissions"),checked:!!d.permissions,onChange:h=>p({...d,permissions:h})})]})},{id:"review",title:l("devStudio.wizard.review","Review"),content:v?e.jsxs("div",{children:[e.jsx("p",{children:l("devStudio.wizard.willCreate","Module {id} with these files:").replace("{id}",v.id)}),e.jsx("ul",{className:"nice-development-studio__list",children:v.files.map(h=>e.jsxs("li",{children:[e.jsx(c.NiceIcon,{name:"file",size:12})," ",h.path]},h.path))})]}):e.jsx("p",{className:"nice-development-studio__muted",children:l("devStudio.wizard.generating","Generating…")})}]})})}function ft({open:t,moduleLabel:a,changes:o,original:r,conflict:u,onSave:i,onOverwrite:s,onReload:l,onClose:n}){const{t:m}=c.useNiceTranslation();return t?e.jsxs(c.NiceModal,{open:t,onClose:n,size:"xl",title:m("devStudio.review.title","Save {module}").replace("{module}",a),"data-testid":"studio-review",footer:u?e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{variant:"ghost",onClick:n,children:m("devStudio.cancel","Cancel")}),e.jsx(c.NiceButton,{variant:"secondary",onClick:l,children:m("devStudio.review.reload","Reload theirs (drop mine)")}),e.jsx(c.NiceButton,{variant:"danger",onClick:s,children:m("devStudio.review.overwrite","Overwrite with mine")})]}):e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{variant:"ghost",onClick:n,children:m("devStudio.cancel","Cancel")}),e.jsx(c.NiceButton,{variant:"primary",onClick:i,children:m("devStudio.review.save","Save {count} files").replace("{count}",String(o.length))})]}),children:[u&&e.jsxs("p",{className:"nice-development-studio__error",role:"alert",children:[m("devStudio.review.conflict","These files changed since you opened them:")," ",u.conflicts.map(d=>d.path).join(", ")]}),o.map(d=>e.jsxs("section",{className:"nice-development-studio__source",children:[e.jsx("h4",{className:"nice-development-studio__source-title",children:d.type==="delete"?m("devStudio.change.delete","Delete {path}").replace("{path}",d.path):d.baseVersion===void 0&&!r(d.path)?m("devStudio.change.new","New file {path}").replace("{path}",d.path):d.path}),e.jsx(De,{before:r(d.path),after:d.type==="write"?d.text:""})]},d.path))]}):null}function vt({open:t,moduleId:a,templates:o,onApply:r,onClose:u}){const{t:i}=c.useNiceTranslation(),s=g.useMemo(()=>o.filter(p=>p.modules.some(v=>v.moduleId===a)).map(p=>p.id),[o,a]),[l,n]=g.useState(s);if(!t)return null;const m=o.map(p=>{var v,k;return{id:p.id,label:((v=p.translations.en)==null?void 0:v.name)??((k=Object.values(p.translations)[0])==null?void 0:k.name)??p.id}}),d=[{field:"label",header:i("devStudio.explorer.name","Name")}];return e.jsx(c.NiceModal,{open:t,onClose:u,title:i("devStudio.picker.title","Templates with {module}").replace("{module}",a),"data-testid":"studio-template-picker",footer:e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{variant:"ghost",onClick:u,children:i("devStudio.cancel","Cancel")}),e.jsx(c.NiceButton,{variant:"primary",onClick:()=>{const p=o.filter(v=>l.includes(v.id)!==s.includes(v.id)).map(v=>({...v,modules:l.includes(v.id)?[...v.modules,{moduleId:a}]:v.modules.filter(k=>k.moduleId!==a)}));r(p)},children:i("devStudio.apply","Apply")})]}),children:e.jsx(c.NiceTreeGrid,{data:m,columns:d,keyField:"id",sortable:!1,compact:!0,checkable:!0,checkedKeys:l,onCheckedChange:n,searchable:!0,"aria-label":i("devStudio.explorer.templates","Templates")})})}function Fe({open:t,title:a,workspaces:o,workspaceId:r,idLabel:u,initialId:i="",withLabel:s,onSubmit:l,onClose:n}){var R;const{t:m}=c.useNiceTranslation(),[d,p]=g.useState(r??((R=o[0])==null?void 0:R.id)??""),[v,k]=g.useState(i),[w,A]=g.useState("");return t?e.jsx(c.NiceModal,{open:t,onClose:n,title:a,footer:e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{variant:"ghost",onClick:n,children:m("devStudio.cancel","Cancel")}),e.jsx(c.NiceButton,{variant:"primary",disabled:!v.trim()||!d,onClick:()=>l({workspaceId:d,id:v.trim(),label:w.trim()||v.trim()}),children:m("devStudio.ok","OK")})]}),children:e.jsxs("div",{className:"nice-development-studio__form",children:[e.jsx(c.NiceSelect,{label:m("devStudio.wizard.workspace","Project"),value:d,options:o.map(L=>({value:L.id,label:L.label})),onChange:L=>p(String(L))}),e.jsx(c.NiceTextInput,{label:u,value:v,onChange:k}),s&&e.jsx(c.NiceTextInput,{label:m("devStudio.package.label","Name"),value:w,onChange:A})]})}):null}const gt=[{target:".nice-i18n-editor",titleKey:"tutorial.i18nEditor.intro.title",title:"Translations",contentKey:"tutorial.i18nEditor.intro.content",content:"Edit translations as a keys × locales grid. Add keys and locales; amber cells mark missing translations.",placement:"auto"},{target:'[data-tour="i18n-grid"]',titleKey:"tutorial.i18nEditor.grid.title",title:"Keys × locales",contentKey:"tutorial.i18nEditor.grid.content",content:"Each row is a translation key and each column a locale. Edit a cell to set a translation; amber cells are still missing.",placement:"top"},{target:'[data-tour="i18n-add"]',titleKey:"tutorial.i18nEditor.add.title",title:"Add keys & locales",contentKey:"tutorial.i18nEditor.add.content",content:"Add a new translation key or a new locale column here; new cells start empty and are flagged as missing.",placement:"top"}],Ce=g.forwardRef(function(a,o){const{value:r,defaultValue:u,onChange:i,locales:s,allowEditLocales:l=!0,allowEditKeys:n=!0,highlightMissing:m=!0,readOnly:d=!1,tutorial:p,className:v,style:k,id:w,"data-testid":A}=a,{t:R}=ue.useNiceTranslation(),[L,j]=ue.useControllableState({value:r,defaultValue:u,fallbackValue:{},onChange:i,componentName:"NiceI18nEditor"}),[$,M]=g.useState(""),[b,E]=g.useState(""),h=g.useMemo(()=>s??Object.keys(L),[s,L]),y=g.useMemo(()=>{const K=new Set;for(const T of Object.keys(L))for(const F of Object.keys(L[T]??{}))K.add(F);return[...K].sort()},[L]),S=(K,T,F)=>{j({...L,[K]:{...L[K]??{},[T]:F}})},O=(K,T)=>{if(!T||T===K)return;const F={};for(const H of Object.keys(L)){const G={...L[H]??{}};K in G&&(G[T]=G[K],delete G[K]),F[H]=G}j(F)},V=K=>{const T={};for(const F of Object.keys(L)){const H={...L[F]??{}};delete H[K],T[F]=H}j(T)},N=()=>{const K=$.trim();if(!K||y.includes(K))return;const T={};for(const F of h)T[F]={...L[F]??{},[K]:""};for(const F of Object.keys(L))T[F]||(T[F]=L[F]);j(T),M("")},J=()=>{const K=b.trim();if(!K||L[K])return;const T={};for(const F of y)T[F]="";j({...L,[K]:T}),E("")},X=K=>{const T={...L};delete T[K],j(T)},Q="nice-i18n-editor"+(v?` ${v}`:"");return e.jsxs("div",{ref:o,id:w,className:Q,style:k,"data-testid":A,children:[p&&e.jsx("div",{className:"nice-i18n-editor__tutorial",children:e.jsx(ue.NiceTutorialButton,{steps:ue.resolveTutorial(p,gt)})}),e.jsx("div",{className:"nice-i18n-editor__scroll","data-tour":"i18n-grid",children:e.jsxs("table",{className:"nice-i18n-editor__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{className:"nice-i18n-editor__key-head",children:R("i18nEditor.keyHead","Key")}),h.map(K=>e.jsxs("th",{className:"nice-i18n-editor__locale-head",children:[e.jsx("span",{children:K}),l&&!d&&e.jsx("button",{type:"button",className:"nice-i18n-editor__locale-remove","aria-label":`${R("i18nEditor.removeLocale","Remove locale")} ${K}`,onClick:()=>X(K),children:e.jsx(ue.NiceIcon,{name:"close",size:12})})]},K))]})}),e.jsxs("tbody",{children:[y.map(K=>e.jsxs("tr",{children:[e.jsxs("td",{className:"nice-i18n-editor__key-cell",children:[n&&!d?e.jsx("input",{className:"nice-i18n-editor__key-input",defaultValue:K,onBlur:T=>O(K,T.target.value.trim()),"aria-label":R("i18nEditor.keyAria","Translation key")}):e.jsx("span",{className:"nice-i18n-editor__key-text",children:K}),n&&!d&&e.jsx("button",{type:"button",className:"nice-i18n-editor__key-remove","aria-label":`${R("i18nEditor.removeKey","Remove key")} ${K}`,onClick:()=>V(K),children:e.jsx(ue.NiceIcon,{name:"close",size:12})})]}),h.map(T=>{var G;const F=((G=L[T])==null?void 0:G[K])??"",H=m&&F==="";return e.jsx("td",{className:"nice-i18n-editor__cell",children:e.jsx("input",{className:"nice-i18n-editor__cell-input"+(H?" nice-i18n-editor__cell-input--missing":""),value:F,readOnly:d,onChange:ee=>S(T,K,ee.target.value),"aria-label":`${K} (${T})`})},T)})]},K)),y.length===0&&e.jsx("tr",{children:e.jsx("td",{className:"nice-i18n-editor__empty",colSpan:h.length+1,children:R("i18nEditor.empty","No translation keys yet.")})})]})]})}),!d&&(n||l)&&e.jsxs("div",{className:"nice-i18n-editor__toolbar","data-tour":"i18n-add",children:[n&&e.jsxs("div",{className:"nice-i18n-editor__add",children:[e.jsx("input",{className:"nice-i18n-editor__add-input",placeholder:R("i18nEditor.newKeyPlaceholder","new.key"),value:$,onChange:K=>M(K.target.value),onKeyDown:K=>{K.key==="Enter"&&N()},"aria-label":R("i18nEditor.newKeyAria","New key")}),e.jsxs("button",{type:"button",onClick:N,children:["+ ",R("i18nEditor.addKey","Key")]})]}),l&&e.jsxs("div",{className:"nice-i18n-editor__add",children:[e.jsx("input",{className:"nice-i18n-editor__add-input",placeholder:R("i18nEditor.newLocalePlaceholder","locale (e.g. de)"),value:b,onChange:K=>E(K.target.value),onKeyDown:K=>{K.key==="Enter"&&J()},"aria-label":R("i18nEditor.newLocaleAria","New locale")}),e.jsxs("button",{type:"button",onClick:J,children:["+ ",R("i18nEditor.addLocale","Locale")]})]})]})]})}),Oe=t=>JSON.stringify(t??null,null,2);function ve({value:t,onChange:a,readOnly:o,height:r=320,label:u}){const{t:i}=c.useNiceTranslation(),[s,l]=g.useState(()=>Oe(t)),[n,m]=g.useState(null),d=g.useRef(t);return g.useEffect(()=>{d.current!==t&&(d.current=t,l(Oe(t)),m(null))},[t]),e.jsxs("div",{className:"nice-development-studio__json",role:"group","aria-label":u,children:[e.jsx(c.NiceSimpleCodeEditor,{value:s,language:"json",height:r,readOnly:o,lineNumbers:!0,onChange:p=>{l(p);try{const v=JSON.parse(p);m(null),d.current=v,a==null||a(v)}catch(v){m(v instanceof Error?v.message:String(v))}}}),n&&e.jsxs("p",{className:"nice-development-studio__error",role:"alert",children:[i("devStudio.json.invalid","Not valid JSON:")," ",n]})]})}function Pe(t){return t.documents.filter(a=>a.kind.editor==="entities").flatMap(a=>t.drafts[a.key]??a.model??[])}function yt(t){return t.documents.filter(a=>a.kind.editor==="dataSources").flatMap(a=>t.drafts[a.key]??a.model??[])}function xt(t){const{module:a,doc:o,session:r,readOnly:u}=t,{t:i}=c.useNiceTranslation(),[s,l]=g.useState(o.model===void 0?"source":"visual"),n=a.changes.filter(d=>o.paths.includes(d.path)||!a.files.some(p=>p.path===d.path)&&o.kind.match(d.path)),m=[{id:"visual",label:i("devStudio.doc.visual","Editor")},{id:"source",label:i("devStudio.doc.source","Source")},{id:"changes",label:`${i("devStudio.doc.changes","Changes")}${n.length?` (${n.length})`:""}`}];return e.jsxs("div",{className:"nice-development-studio__document","data-testid":`studio-doc-${o.key}`,children:[e.jsxs("div",{className:"nice-development-studio__doc-bar",children:[e.jsx(c.NiceIcon,{name:o.kind.icon??"file",size:14}),e.jsx("strong",{className:"nice-development-studio__doc-title",children:o.label}),e.jsx("span",{className:"nice-development-studio__muted",children:o.paths.length===1?o.paths[0]:i("devStudio.doc.files","{count} files").replace("{count}",String(o.paths.length))}),e.jsx("span",{className:"nice-development-studio__spacer"}),e.jsx("div",{className:"nice-development-studio__segmented",role:"group","aria-label":i("devStudio.doc.mode","Show"),children:m.map(d=>e.jsx(c.NiceButton,{size:"sm",variant:s===d.id?"primary":"ghost","aria-pressed":s===d.id,disabled:d.id==="visual"&&o.model===void 0,onClick:()=>l(d.id),children:d.label},d.id))})]}),o.error&&e.jsxs("p",{className:"nice-development-studio__error",role:"alert",children:[i("devStudio.doc.unreadable","This file could not be read as its kind; edit its source.")," ",o.error]}),s==="visual"&&o.model!==void 0&&e.jsx(bt,{...t}),s==="source"&&e.jsx("div",{className:"nice-development-studio__sources",children:o.paths.map(d=>e.jsxs("section",{className:"nice-development-studio__source",children:[e.jsx("h4",{className:"nice-development-studio__source-title",children:d}),e.jsx(c.NiceSimpleCodeEditor,{value:a.pending.get(d)??"",language:d.endsWith(".json")?"json":d.endsWith(".js")?"javascript":"plaintext",height:360,lineNumbers:!0,readOnly:u,onChange:p=>r.setRaw(a.key,d,P.keepTextFormat(p,a.pending.get(d)),[o.key])})]},d))}),s==="changes"&&e.jsxs("div",{className:"nice-development-studio__sources",children:[n.length===0&&e.jsx("p",{className:"nice-development-studio__muted",children:i("devStudio.diff.none","No changes.")}),n.map(d=>{var p;return e.jsxs("section",{className:"nice-development-studio__source",children:[e.jsx("h4",{className:"nice-development-studio__source-title",children:d.type==="delete"?i("devStudio.change.delete","Delete {path}").replace("{path}",d.path):a.files.some(v=>v.path===d.path)?d.path:i("devStudio.change.new","New file {path}").replace("{path}",d.path)}),e.jsx(De,{before:((p=a.files.find(v=>v.path===d.path))==null?void 0:p.text)??"",after:d.type==="write"?d.text:""})]},d.path)})]})]})}function bt(t){var m,d,p,v,k,w;const{module:a,doc:o,preset:r,session:u,locales:i,readOnly:s}=t,l=a.drafts[o.key]??o.model,n=A=>u.setDraft(a.key,o.key,A);switch(o.kind.editor){case"manifest":return e.jsx(kt,{value:l??{},onChange:n,sections:r.manifestSections??[],readOnly:s});case"entities":return e.jsx(Te,{value:l??[],onChange:n,entityMetaSchema:(m=r.entities)==null?void 0:m.entityMetaSchema,fieldSchema:(d=r.entities)==null?void 0:d.fieldSchema,fieldsKey:(p=r.entities)==null?void 0:p.fieldsKey,nameKey:(v=r.entities)==null?void 0:v.nameKey,readOnly:s});case"i18n":{const A=l??{};return e.jsx(Ce,{value:A,onChange:n,locales:[...new Set([...i,...Object.keys(A)])],allowEditLocales:!0,allowEditKeys:!0,highlightMissing:!0,readOnly:s})}case"views":return e.jsx(jt,{...t,items:l??[],onChange:n});case"workflows":return e.jsx(Le,{items:l??[],onChange:n,readOnly:s,kind:"workflow",create:A=>({id:`workflow-${A}`,name:`Workflow ${A}`,entityType:"",version:1,states:[],transitions:[]}),render:(A,R)=>e.jsx(c.NiceWorkflowDesigner,{workflow:A,onChange:R,readOnly:s})});case"permissions":return e.jsx(St,{value:l??{permissions:[],groups:[]},onChange:n,readOnly:s});case"rbac":return e.jsx(c.NiceAccessManager,{value:l,onChange:n,readOnly:s});case"dataSources":return e.jsx(Nt,{value:l??[],onChange:n,entities:Pe(a),readOnly:s});case"seeds":return e.jsx(wt,{value:l??{seeds:{}},onChange:n,readOnly:s});case"hooks":return e.jsx(c.NiceLifecycleHooksEditor,{triggers:((k=r.hooks)==null?void 0:k.triggers)??[],handlers:(w=r.hooks)==null?void 0:w.handlers,bindings:l??[],onChange:n,groupByTrigger:!0,allowCondition:!0,readOnly:s});case"script":return t.scriptRunner?e.jsx(c.NiceScriptRunner,{...t.scriptRunner,value:String(l??""),onChange:n}):e.jsx(c.NiceSimpleCodeEditor,{value:String(l??""),onChange:n,language:"javascript",height:420,lineNumbers:!0,readOnly:s});case"text":return e.jsx(c.NiceSimpleCodeEditor,{value:String(l??""),onChange:n,height:420,lineNumbers:!0,readOnly:s});default:return e.jsx(ve,{value:l,onChange:n,readOnly:s,height:420,label:o.label})}}function kt({value:t,onChange:a,sections:o,readOnly:r}){const{t:u}=c.useNiceTranslation(),i=g.useMemo(()=>o.map(m=>P.fitManifestSection(m,t)),[o,t]),s=g.useMemo(()=>new Set(i.flatMap(m=>m.keys)),[i]),l=g.useMemo(()=>Object.fromEntries(Object.entries(t).filter(([m])=>!s.has(m))),[t,s]),n=e.jsx(ve,{value:l,readOnly:r,label:u("devStudio.manifest.other","Other properties"),onChange:m=>{if(m&&typeof m=="object"&&!Array.isArray(m)){const d=Object.fromEntries(Object.entries(t).filter(([p])=>s.has(p)));a({...d,...m})}}});return o.length===0?n:e.jsx(c.NiceTabs,{tabs:[...i.map(({section:m,keys:d})=>({id:m.id,label:m.title,content:e.jsx(pe,{schema:m.schema,fields:m.fields,uiSchema:m.uiSchema,value:Object.fromEntries(d.filter(p=>p in t).map(p=>[p,t[p]])),onChange:p=>{const v={...t};for(const k of d)p[k]===void 0?delete v[k]:v[k]=p[k];a(v)},readOnly:r,showJsonView:!0})})),{id:"__other",label:u("devStudio.manifest.other","Other properties"),content:n}]})}function Le({items:t,onChange:a,readOnly:o,kind:r,create:u,render:i}){var v;const{t:s}=c.useNiceTranslation(),[l,n]=g.useState(((v=t[0])==null?void 0:v.key)??null),m=t.find(k=>k.key===l)??null,d=r==="view"?{pick:s("devStudio.items.pickView","View"),add:s("devStudio.items.addView","New view"),empty:s("devStudio.items.noViews","No views yet.")}:{pick:s("devStudio.items.pickWorkflow","Workflow"),add:s("devStudio.items.addWorkflow","New workflow"),empty:s("devStudio.items.noWorkflows","No workflows yet.")},p=(k,w)=>{a(t.map(A=>A.key===k?w:A)),w.key!==k&&n(w.key)};return e.jsxs("div",{className:"nice-development-studio__items",children:[e.jsxs("div",{className:"nice-development-studio__items-bar",children:[e.jsxs("label",{className:"nice-development-studio__field",children:[e.jsx("span",{children:d.pick}),e.jsxs("select",{value:l??"",onChange:k=>n(k.target.value||null),children:[t.length===0&&e.jsx("option",{value:"",children:d.empty}),t.map(k=>e.jsxs("option",{value:k.key,children:[k.label,k.definition?"":` (${s("devStudio.items.raw","JSON")})`]},k.key))]})]}),!o&&e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:()=>{const k=u(t.length+1),w={key:k.id,label:k.name,definition:k,source:k};a([...t,w]),n(w.key)},children:d.add}),m&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"trash",size:14}),onClick:()=>{a(t.filter(k=>k.key!==m.key)),n(null)},children:s("devStudio.delete","Delete")})]})]}),(m==null?void 0:m.definition)!==void 0&&i(m.definition,k=>p(m.key,{...m,definition:k,label:k.name||m.label,key:k.id&&!t.some(w=>w!==m&&w.key===k.id)?k.id:m.key}),m),m&&m.definition===void 0&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"nice-development-studio__muted",children:[s("devStudio.items.rawReason","The editor does not know this shape, so it is edited as JSON."),m.rawReason?` (${m.rawReason})`:""]}),e.jsx(ve,{value:m.source,readOnly:o,label:m.label,onChange:k=>p(m.key,{...m,source:k})})]}),!m&&e.jsx("p",{className:"nice-development-studio__muted",children:d.empty})]})}function jt({module:t,items:a,onChange:o,readOnly:r,renderViewPreview:u}){const{t:i}=c.useNiceTranslation(),s=Pe(t),l=yt(t).map(n=>({key:n.key,label:n.label}));return e.jsx(Le,{items:a,onChange:o,readOnly:r,kind:"view",create:n=>({id:`view-${n}`,name:`View ${n}`,version:2,columns:12,rows:[],dataSources:[]}),render:(n,m,d)=>{const p=e.jsx(c.NiceViewEditor,{value:n,onChange:m,entities:s,dataSourceOptions:l,height:540});return u?e.jsx(c.NiceTabs,{tabs:[{id:"design",label:i("devStudio.view.design","Design"),content:p},{id:"preview",label:i("devStudio.view.hostPreview","Preview in the app"),content:u({module:t.key,item:{...d,definition:n},files:t.working})}]}):p}})}function Nt({value:t,onChange:a,entities:o,readOnly:r}){var m;const{t:u}=c.useNiceTranslation(),[i,s]=g.useState(((m=t[0])==null?void 0:m.key)??null),l=t.find(d=>d.key===i)??null,n=g.useMemo(()=>P.entitiesToSchemas(o),[o]);return e.jsxs("div",{className:"nice-development-studio__items",children:[e.jsxs("div",{className:"nice-development-studio__items-bar",children:[e.jsxs("label",{className:"nice-development-studio__field",children:[e.jsx("span",{children:u("devStudio.items.pickDataSource","Data source")}),e.jsxs("select",{value:i??"",onChange:d=>s(d.target.value||null),children:[t.length===0&&e.jsx("option",{value:"",children:u("devStudio.items.noDataSources","No data sources yet.")}),t.map(d=>e.jsx("option",{value:d.key,children:d.label||d.key},d.key))]})]}),!r&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:()=>{const d={key:`source${t.length+1}`,kind:"query",query:{tables:[],joins:[],conditions:[],sorts:[],groupBy:[],distinct:!1},sql:""};a([...t,d]),s(d.key)},children:u("devStudio.items.addDataSource","New data source")})]}),l&&e.jsx(c.NiceDataSourceBuilder,{value:l,schemas:n,onChange:d=>{a(t.map(p=>p.key===l.key?d:p)),s(d.key)}})]})}function St({value:t,onChange:a,readOnly:o}){const{t:r}=c.useNiceTranslation(),u={code:r("devStudio.permissions.code","Code"),name:r("devStudio.permissions.name","Name"),description:r("devStudio.permissions.description","Description")},i=g.useMemo(()=>{const l={};for(const n of t.groups)for(const m of n.permissions)l[`${n.id}:${m}`]=!0;return l},[t.groups]),s=(l,n)=>{const m=t.permissions[l],d={...m,...n};a({permissions:t.permissions.map((p,v)=>v===l?d:p),groups:n.code!==void 0&&n.code!==m.code?t.groups.map(p=>({...p,permissions:p.permissions.map(v=>v===m.code?d.code:v)})):t.groups})};return e.jsxs("div",{className:"nice-development-studio__permissions",children:[e.jsx("h4",{children:r("devStudio.permissions.codes","Permissions")}),e.jsxs("table",{className:"nice-development-studio__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:u.code}),e.jsx("th",{children:u.name}),e.jsx("th",{children:u.description}),!o&&e.jsx("th",{"aria-label":r("devStudio.delete","Delete")})]})}),e.jsx("tbody",{children:t.permissions.map((l,n)=>e.jsxs("tr",{children:[["code","name","description"].map(m=>e.jsx("td",{children:e.jsx("input",{className:"nice-development-studio__cell",value:l[m]??"",readOnly:o,"aria-label":`${u[m]} ${l.code}`,onChange:d=>s(n,{[m]:d.target.value})})},m)),!o&&e.jsx("td",{children:e.jsx(c.NiceButton,{size:"sm",variant:"ghost",ariaLabel:`${r("devStudio.delete","Delete")} ${l.code}`,onClick:()=>a({permissions:t.permissions.filter((m,d)=>d!==n),groups:t.groups.map(m=>({...m,permissions:m.permissions.filter(d=>d!==l.code)}))}),children:e.jsx(c.NiceIcon,{name:"trash",size:14})})})]},n))})]}),!o&&e.jsxs("div",{className:"nice-development-studio__row",children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:()=>a({...t,permissions:[...t.permissions,{code:`New.Permission${t.permissions.length+1}`}]}),children:r("devStudio.permissions.addCode","New permission")}),e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:()=>a({...t,groups:[...t.groups,{id:`group${t.groups.length+1}`,label:r("devStudio.permissions.newGroup","Group {n}").replace("{n}",String(t.groups.length+1)),permissions:[]}]}),children:r("devStudio.permissions.addGroup","New group")})]}),e.jsx("h4",{children:r("devStudio.permissions.groups","Groups")}),e.jsx(c.NicePermissionMatrix,{roles:t.groups.map(l=>({id:l.id,label:l.label})),actions:t.permissions.map(l=>({id:l.code,label:l.name||l.code})),value:i,readOnly:o,showBulkActions:!0,onChange:l=>a({...t,groups:t.groups.map(n=>({...n,permissions:t.permissions.map(m=>m.code).filter(m=>l[`${n.id}:${m}`]===!0)}))})})]})}function wt({value:t,onChange:a,readOnly:o}){const{t:r}=c.useNiceTranslation(),u=i=>{const s=t[i]??{},l=Object.keys(s);return l.length===0?e.jsx("p",{className:"nice-development-studio__muted",children:r("devStudio.seeds.empty","No rows.")}):e.jsx(c.NiceTabs,{tabs:l.map(n=>({id:n,label:`${n} (${s[n].length})`,content:e.jsx(ve,{value:s[n],readOnly:o,label:n,onChange:m=>{Array.isArray(m)&&a({...t,[i]:{...s,[n]:m}})}})}))})};return e.jsx(c.NiceTabs,{tabs:[{id:"seeds",label:r("devStudio.seeds.data","Data"),content:u("seeds")},{id:"demo",label:r("devStudio.seeds.demo","Demo data"),content:u("demoSeeds")}]})}const Y=t=>`${t.workspaceId}/${t.id}`;function Se(t,a,o){const r=new Set(t.deleted),u=new Map;for(const v of t.files)r.has(v.path)||u.set(v.path,t.raw[v.path]!==void 0?{...v,text:t.raw[v.path]}:v);for(const[v,k]of Object.entries(t.raw))!u.has(v)&&!r.has(v)&&u.set(v,{path:v,text:k});const i=[...u.values()],s={moduleId:t.key.id,files:i,locales:o},l=P.buildDocuments(a.kinds,i,s),n=new Map(i.map(v=>[v.path,v.text])),m={};for(const v of l)if(v.key in t.drafts)try{const k=v.kind.encode(t.drafts[v.key],i.filter(w=>v.paths.includes(w.path)),s);for(const w of k.files)n.set(w.path,w.text),r.delete(w.path);for(const w of k.deleted??[])n.delete(w),r.add(w)}catch(k){m[v.key]=k instanceof Error?k.message:String(k)}const d=new Map(t.files.map(v=>[v.path,v])),p=[];for(const[v,k]of n){const w=d.get(v);(!w||w.text!==k)&&p.push({type:"write",path:v,text:k,baseVersion:w==null?void 0:w.version})}for(const v of r){const k=d.get(v);k&&p.push({type:"delete",path:v,baseVersion:k.version})}return{...t,working:i,documents:l,changes:p,pending:n,encodeErrors:m,dirty:p.length>0}}function Ae(t,a){const o=[];for(const r of t.documents){if(r.error&&o.push({severity:"error",code:"file.unreadable",message:`${r.paths[0]} cannot be read: ${r.error}`,messageKey:"devStudio.issue.unreadable",params:{path:r.paths[0]},moduleId:t.key.id,path:r.paths[0]}),r.kind.editor!=="manifest"||!a.manifestSections)continue;const u=t.drafts[r.key]??r.model??{};for(const i of a.manifestSections){const{section:s}=P.fitManifestSection(i,u);if(s.schema)for(const l of Ie(u,s.schema))o.push({severity:"error",code:"manifest.schema",message:`${s.title}: ${l.field} — ${l.message}`,moduleId:t.key.id,path:r.paths[0],pointer:`/${l.field.replace(/\./g,"/")}`})}}for(const[r,u]of Object.entries(t.encodeErrors))o.push({severity:"error",code:"document.encode",message:`${r}: ${u}`,moduleId:t.key.id});if(a.validateModule){const r=[...t.pending.entries()].map(([u,i])=>({path:u,text:i}));o.push(...a.validateModule({key:t.key,files:r,documents:t.documents}).map(u=>({...u,moduleId:u.moduleId??t.key.id})))}return o}const _t=t=>t instanceof Error?t.message:String(t);function It(t,a,o){const[r,u]=g.useState([]),[i,s]=g.useState({}),[l,n]=g.useState({}),[m,d]=g.useState(null),[p,v]=g.useState({}),[k,w]=g.useState({}),[A,R]=g.useState(0),[L,j]=g.useState([]),$=g.useRef({provider:t,preset:a,options:o});$.current={provider:t,preset:a,options:o};const M=g.useCallback((_,I,x)=>{j(C=>[...C,{level:_,message:I,data:x,timestamp:Date.now()}].slice(-300))},[]),b=g.useCallback(async(_,I)=>{var x,C;R(B=>B+1);try{return await I()}catch(B){M("error",`${_}: ${_t(B)}`),(C=(x=$.current.options).onError)==null||C.call(x,B,_);return}finally{R(B=>B-1)}},[M]),E=g.useCallback(async()=>{const _=$.current.provider;_&&await b("List",async()=>{const I=await _.listWorkspaces();u(I);const x=await Promise.all(I.map(async C=>{const[B,q]=await Promise.all([_.listModules(C.id),_.listPackages?_.listPackages(C.id):Promise.resolve(void 0)]);return[C.id,B,q]}));s(Object.fromEntries(x.map(([C,B])=>[C,B]))),n(Object.fromEntries(x.filter(([,,C])=>C).map(([C,,B])=>[C,B]))),d(_.listTemplates?await _.listTemplates():null)})},[b]);g.useEffect(()=>{E()},[t,E]);const h=g.useMemo(()=>{const _={};for(const[I,x]of Object.entries(p))_[I]=Se(x,a,o.locales);return _},[p,a,o.locales]),y=g.useCallback(async _=>{const I=Y(_),x=$.current.provider;if(!x)return;const C=await b(`Open ${_.id}`,()=>x.readModule(_));if(!C)return;const B={key:_,files:C,raw:{},deleted:[],drafts:{}};return v(q=>q[I]?q:{...q,[I]:B}),M("info",`Opened ${_.id} (${C.length} files)`),Se(B,$.current.preset,$.current.options.locales)},[b,M]),S=g.useCallback((_,I)=>{const x=Y(_);v(C=>C[x]?{...C,[x]:I(C[x])}:C)},[]),O=g.useCallback((_,I,x)=>S(_,C=>({...C,drafts:{...C.drafts,[I]:x}})),[S]),V=g.useCallback((_,I,x,C=[])=>S(_,B=>{const q={...B.raw};x===null?delete q[I]:q[I]=x;const W={...B.drafts};for(const U of C)delete W[U];return{...B,raw:q,drafts:W,deleted:B.deleted.filter(U=>U!==I)}}),[S]),N=g.useCallback((_,I)=>S(_,x=>{const C={...x.raw};delete C[I];const B=!x.files.some(q=>q.path===I);return{...x,raw:C,deleted:B?x.deleted:[...new Set([...x.deleted,I])]}}),[S]),J=g.useCallback(_=>S(_,I=>({...I,raw:{},deleted:[],drafts:{}})),[S]),X=g.useCallback(async _=>{const I=$.current.provider;if(!I)return;const x=await b(`Reload ${_.id}`,()=>I.readModule(_));x&&(S(_,()=>({key:_,files:x,raw:{},deleted:[],drafts:{}})),M("info",`Reloaded ${_.id}`))},[b,S,M]),Q=g.useCallback(_=>{const I=Y(_);v(x=>{const C={...x};return delete C[I],C})},[]),K=g.useCallback(async(_,I={})=>{var le;const x=$.current.provider,C=Y(_),B=p[C];if(!x||!B)return;const q=Se(B,$.current.preset,$.current.options.locales);if(q.changes.length===0)return{ok:!0};const W=I.force?q.changes.map(Z=>({...Z,baseVersion:void 0})):q.changes,U=await b(`Save ${_.id}`,()=>x.writeModule(_,W));if(!U)return;if(!U.ok)return M("warn",`${_.id}: ${U.conflicts.length} file(s) changed meanwhile`),U;const oe=[];for(const[Z,ge]of q.pending){const me=B.files.find(se=>se.path===Z);oe.push({...me,path:Z,text:ge,version:((le=U.versions)==null?void 0:le[Z])??(me==null?void 0:me.version)})}return S(_,()=>({key:_,files:oe,raw:{},deleted:[],drafts:{}})),M("info",`Saved ${_.id}: ${W.map(Z=>`${Z.type} ${Z.path}`).join(", ")}`),U},[p,b,S,M]),T=g.useCallback(async _=>{const I=Y(_),x=h[I];if(!x)return[];const C=Ae(x,a),B=$.current.provider;let q=[];if(B!=null&&B.validate){const U=[...x.pending.entries()].map(([oe,le])=>({path:oe,text:le}));q=await b(`Validate ${_.id}`,()=>B.validate(_,U))??[]}w(U=>({...U,[I]:q}));const W=[...C,...q];M(W.some(U=>U.severity==="error")?"warn":"info",W.length===0?`${_.id}: no problems`:`${_.id}: ${W.length} problem(s)`);for(const U of W)M(U.severity==="error"?"error":U.severity==="warning"?"warn":"info",`${U.path?`${U.path}: `:""}${U.message}`);return W},[h,a,b,M]),F=g.useCallback(async _=>{const{provider:I,preset:x}=$.current;if(!(I!=null&&I.createModule)||!x.generateModule)return;const C=new Set(Object.values(i).flatMap(W=>W.map(U=>U.id))),B=await b("Generate module",()=>x.generateModule(_,{existingIds:C}));if(!B)return;const q=await b(`Create ${B.id}`,()=>I.createModule({workspaceId:_.workspaceId,packageId:B.packageId??_.packageId,id:B.id,files:B.files}));return q&&(M("info",`Created ${q.id}`),await E()),q},[i,b,M,E]),H=g.useCallback(async(_,I)=>{const{provider:x,preset:C}=$.current;if(!(x!=null&&x.createModule)||!C.duplicateModule)return;const B=await b(`Read ${_.id}`,()=>x.readModule(_));if(!B)return;const q=await b("Duplicate",()=>C.duplicateModule(B,I));if(!q)return;const W=await b(`Create ${q.id}`,()=>x.createModule({workspaceId:I.workspaceId,packageId:q.packageId??I.packageId,id:q.id,files:q.files}));return W&&(M("info",`Duplicated ${_.id} as ${W.id}`),await E()),W},[b,M,E]),G=g.useCallback(async _=>{const I=$.current.provider;if(!(I!=null&&I.deleteModule))return!1;const x=await b(`Delete ${_.id}`,async()=>(await I.deleteModule(_),!0));return x&&(Q(_),M("info",`Deleted ${_.id}`),await E()),!!x},[b,Q,M,E]),ee=g.useCallback(async _=>{const I=$.current.provider;if(!(I!=null&&I.savePackage))return;const x=await b(`Save package ${_.id}`,()=>I.savePackage(_));return x&&(M("info",`Saved package ${x.id}`),await E()),x},[b,M,E]),te=g.useCallback(async(_,I)=>{const x=$.current.provider;if(!(x!=null&&x.saveTemplate))return;const C=await b(`Save template ${_.id}`,()=>x.saveTemplate(_,I?{previousId:I}:void 0));return C&&x.listTemplates&&(d(await x.listTemplates()),M("info",`Saved template ${C.id}`)),C},[b,M]),ae=g.useCallback(async _=>{const I=$.current.provider;if(!(I!=null&&I.deleteTemplate))return!1;const x=await b(`Delete template ${_}`,async()=>(await I.deleteTemplate(_),!0));return x&&I.listTemplates&&(d(await I.listTemplates()),M("info",`Deleted template ${_}`)),!!x},[b,M]);return{workspaces:r,modulesByWs:i,packagesByWs:l,templates:m,modules:h,serverIssues:k,busy:A>0,logs:L,clearLogs:()=>j([]),log:M,refresh:E,openModule:y,close:Q,setDraft:O,setRaw:V,deleteFile:N,discard:J,reload:X,save:K,validate:T,createModule:F,duplicateModule:H,deleteModule:G,savePackage:ee,saveTemplate:te,deleteTemplate:ae}}const re="__none";function ze(t,a,o){const r=new Map((a??[]).map(u=>[u.id,u]));for(const u of o){const i=u.packageId??re;r.has(i)||r.set(i,{id:i,workspaceId:t,label:u.packageId??"",derived:!0})}return[...r.values()].sort((u,i)=>u.id===re?1:i.id===re?-1:u.label.localeCompare(i.label))}function Tt({session:t,provider:a,canCreateModule:o,canDuplicateModule:r,issueCounts:u,actions:i,defaultTab:s,readOnly:l}){var E;const{t:n}=c.useNiceTranslation(),[m,d]=g.useState(a!=null&&a.listTemplates?s:"modules"),[p,v]=g.useState(null),k=n("devStudio.explorer.noPackage","No package"),w=g.useMemo(()=>t.workspaces.map(h=>{const y=t.modulesByWs[h.id]??[];return{id:`w:${h.id}`,kind:"workspace",label:h.label,icon:h.icon??"folder",info:String(y.length),workspaceId:h.id,readOnly:h.readOnly,children:ze(h.id,t.packagesByWs[h.id],y).map(S=>({id:`w:${h.id}/p:${S.id}`,kind:"package",label:S.id===re?k:S.label||S.id,icon:S.icon??"archive",workspaceId:h.id,packageId:S.id===re?void 0:S.id,children:y.filter(O=>(O.packageId??re)===S.id).sort((O,V)=>O.label.localeCompare(V.label)).map(O=>{const V=Y(O),N=t.modules[V];return{id:`w:${h.id}/p:${S.id}/m:${O.id}`,kind:"module",label:O.label,icon:O.icon&&/^[a-z0-9-]+$/.test(O.icon)?O.icon:"box",info:O.version??(N?String(N.working.length):O.files?String(O.files.length):void 0),workspaceId:h.id,packageId:O.packageId,moduleId:O.id,readOnly:O.readOnly,shadowedBy:O.shadowedBy,dirty:N==null?void 0:N.dirty,issues:u[V],search:`${O.id} ${O.description??""} ${O.search??""}`,children:N==null?void 0:N.documents.map(J=>({id:`w:${h.id}/p:${S.id}/m:${O.id}/d:${J.key}`,kind:"document",label:J.label,icon:J.kind.icon??"file",info:J.paths.length>1?String(J.paths.length):void 0,workspaceId:h.id,moduleId:O.id,docKey:J.key,dirty:J.key in N.drafts||J.paths.some(X=>X in N.raw),search:J.paths.join(" ")}))}})}))}}),[t.workspaces,t.modulesByWs,t.packagesByWs,t.modules,u,k]),A=g.useMemo(()=>{const h=new Map;for(const y of Object.values(t.modulesByWs))for(const S of y)h.has(S.id)||h.set(S.id,S);return h},[t.modulesByWs]),R=g.useMemo(()=>{const h=new Map;for(const S of t.templates??[]){const O=S.category??"";h.set(O,[...h.get(O)??[],S])}const y=S=>{var O,V;return((O=S.translations.en)==null?void 0:O.name)??((V=Object.values(S.translations)[0])==null?void 0:V.name)??S.id};return[...h.entries()].sort(([S],[O])=>S.localeCompare(O)).map(([S,O])=>({id:`c:${S}`,kind:"category",label:S||n("devStudio.explorer.noCategory","Other"),icon:"folder",info:String(O.length),children:O.sort((V,N)=>(V.sortOrder??0)-(N.sortOrder??0)||y(V).localeCompare(y(N))).map(V=>({id:`c:${S}/t:${V.id}`,kind:"template",label:y(V),icon:V.icon&&/^[a-z0-9-]+$/.test(V.icon)?V.icon:"layers",info:String(V.modules.length),templateId:V.id,search:`${V.id} ${(V.tags??[]).join(" ")}`,children:V.modules.map(N=>{const J=A.get(N.moduleId);return{id:`c:${S}/t:${V.id}/m:${N.moduleId}`,kind:"templateModule",label:(J==null?void 0:J.label)??N.moduleId,icon:"box",info:N.required?n("devStudio.template.required","required"):void 0,templateId:V.id,moduleId:N.moduleId,workspaceId:J==null?void 0:J.workspaceId,missing:!J}})}))}))},[t.templates,A,n]),L=g.useMemo(()=>[{field:"label",header:n("devStudio.explorer.name","Name"),render:(h,y)=>e.jsxs("span",{className:"nice-development-studio__tree-name",children:[e.jsx(c.NiceIcon,{name:y.icon,size:14}),e.jsx("span",{className:y.missing?"nice-development-studio__missing":void 0,children:y.label}),y.dirty&&e.jsx("span",{className:"nice-development-studio__dot",title:n("devStudio.explorer.unsaved","Unsaved changes"),children:e.jsx(c.NiceIcon,{name:"circle",size:8})}),!!y.issues&&e.jsx("span",{className:"nice-development-studio__badge",title:n("devStudio.explorer.problems","Problems"),children:y.issues}),y.readOnly&&e.jsx("span",{title:n("devStudio.explorer.readOnly","Read-only"),children:e.jsx(c.NiceIcon,{name:"lock",size:12})}),y.shadowedBy&&e.jsx("span",{className:"nice-development-studio__tag",title:y.shadowedBy,children:n("devStudio.explorer.shadowed","shadowed")}),y.missing&&e.jsx("span",{className:"nice-development-studio__tag",children:n("devStudio.explorer.missing","missing")})]})},{field:"info",header:"",width:64,align:"right"}],[n]),j=h=>h.workspaceId&&h.moduleId?{workspaceId:h.workspaceId,id:h.moduleId}:null,$=h=>{v(h);const y=j(h);if(h.kind==="module"&&y)i.openModule(y);else if(h.kind==="document"&&y&&h.docKey)i.openDocument(y,h.docKey);else if(h.kind==="package"&&h.workspaceId){const S=ze(h.workspaceId,t.packagesByWs[h.workspaceId],t.modulesByWs[h.workspaceId]??[]).find(O=>(O.id===re?void 0:O.id)===h.packageId);S&&S.id!==re&&i.openPackage(S)}else h.kind==="template"&&h.templateId?i.openTemplate(h.templateId):h.kind==="templateModule"&&y&&i.openModule(y)},M=p&&(p.kind==="module"||p.kind==="templateModule")?j(p):null,b=h=>{var y;return!l&&!!h&&!((y=t.workspaces.find(S=>S.id===h))!=null&&y.readOnly)};return e.jsxs("div",{className:"nice-development-studio__explorer","data-tour":"devstudio-explorer",children:[(a==null?void 0:a.listTemplates)&&e.jsxs("div",{className:"nice-development-studio__segmented",role:"group","aria-label":n("devStudio.explorer.show","Show"),children:[e.jsx(c.NiceButton,{size:"sm",variant:m==="modules"?"primary":"ghost","aria-pressed":m==="modules",onClick:()=>d("modules"),children:n("devStudio.explorer.modules","Modules")}),e.jsx(c.NiceButton,{size:"sm",variant:m==="templates"?"primary":"ghost","aria-pressed":m==="templates",onClick:()=>d("templates"),children:n("devStudio.explorer.templates","Templates")})]}),e.jsxs("div",{className:"nice-development-studio__explorer-actions",children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",ariaLabel:n("devStudio.refresh","Refresh"),onClick:()=>void t.refresh(),children:e.jsx(c.NiceIcon,{name:"refresh",size:14})}),m==="modules"&&o&&!l&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:()=>i.newModule({workspaceId:p==null?void 0:p.workspaceId,packageId:p==null?void 0:p.packageId}),children:n("devStudio.explorer.newModule","Module")}),m==="modules"&&(a==null?void 0:a.savePackage)&&!l&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),disabled:!b((p==null?void 0:p.workspaceId)??((E=t.workspaces.find(h=>!h.readOnly))==null?void 0:E.id)),onClick:()=>{var h;return i.newPackage((p==null?void 0:p.workspaceId)??((h=t.workspaces.find(y=>!y.readOnly))==null?void 0:h.id)??"")},children:n("devStudio.explorer.newPackage","Package")}),m==="templates"&&(a==null?void 0:a.saveTemplate)&&!l&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:()=>i.newTemplate(),children:n("devStudio.explorer.newTemplate","Template")}),M&&e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",ariaLabel:n("devStudio.validate","Validate"),onClick:()=>i.validateModule(M),children:e.jsx(c.NiceIcon,{name:"check",size:14})}),(a==null?void 0:a.saveTemplate)&&!l&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",ariaLabel:n("devStudio.explorer.addToTemplate","Add to template"),onClick:()=>i.addToTemplate(M),children:e.jsx(c.NiceIcon,{name:"layers",size:14})}),r&&!l&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",ariaLabel:n("devStudio.explorer.duplicate","Duplicate"),onClick:()=>i.duplicateModule(M),children:e.jsx(c.NiceIcon,{name:"copy",size:14})}),(a==null?void 0:a.deleteModule)&&b(M.workspaceId)&&!(p!=null&&p.readOnly)&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",ariaLabel:n("devStudio.delete","Delete"),onClick:()=>i.deleteModule(M),children:e.jsx(c.NiceIcon,{name:"trash",size:14})})]})]}),e.jsx("div",{className:"nice-development-studio__tree",children:m==="modules"?e.jsx(c.NiceTreeGrid,{data:w,nested:!0,keyField:"id",childrenField:"children",columns:L,sortable:!1,compact:!0,searchable:!0,searchFields:["label","search"],searchPlaceholder:n("devStudio.explorer.search","Search modules and files"),toolbarActions:["collapseAll"],defaultExpandedKeys:t.workspaces.map(h=>`w:${h.id}`),hasChildren:h=>h.kind==="module",loadChildren:async h=>{const y=j(h);return y&&!t.modules[Y(y)]&&await t.openModule(y),[]},onRowClick:$,rowClassName:h=>(p==null?void 0:p.id)===h.id?"nice-development-studio__tree-row--selected":void 0,emptyText:n("devStudio.explorer.empty","No modules."),"aria-label":n("devStudio.explorer.modules","Modules"),"data-testid":"studio-modules-tree"},"modules"):e.jsx(c.NiceTreeGrid,{data:R,nested:!0,keyField:"id",childrenField:"children",columns:L,sortable:!1,compact:!0,searchable:!0,searchFields:["label","search"],searchPlaceholder:n("devStudio.explorer.searchTemplates","Search templates"),onRowClick:$,rowClassName:h=>(p==null?void 0:p.id)===h.id?"nice-development-studio__tree-row--selected":void 0,emptyText:n("devStudio.explorer.noTemplates","No templates."),"aria-label":n("devStudio.explorer.templates","Templates"),"data-testid":"studio-templates-tree"},"templates")})]})}function Ct({module:t,moduleRef:a,session:o,provider:r,preset:u,issues:i,readOnly:s,panels:l,onOpenDocument:n,onSave:m}){const{t:d}=c.useNiceTranslation(),p=j=>j.labelKey?d(j.labelKey,j.label):j.label,[v,k]=g.useState(null),w=t.key;g.useEffect(()=>{let j=!0;return r!=null&&r.listRevisions&&r.listRevisions(w).then($=>{j&&k($.map(M=>({id:M.id,label:M.label,author:M.author,timestamp:M.timestamp,summary:M.summary})))}).catch(()=>k([])),()=>{j=!1}},[r,w,t.files]);const A=j=>t.documents.find($=>j&&$.paths.includes(j)),R=u.newFile?u.kinds.filter(j=>{var M;const $=(M=u.newFile)==null?void 0:M.call(u,j.id,{key:w,files:t.working,documents:t.documents});return!!$&&!t.working.some(b=>b.path===$.path)}):[],L=[{id:"documents",label:`${d("devStudio.overview.documents","Documents")} (${t.documents.length})`,content:e.jsx("ul",{className:"nice-development-studio__list",children:t.documents.map(j=>e.jsxs("li",{children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:j.kind.icon??"file",size:14}),onClick:()=>n(j.key),children:j.label}),e.jsx("span",{className:"nice-development-studio__muted",children:p(j.kind)}),(j.key in t.drafts||j.paths.some($=>$ in t.raw))&&e.jsx("span",{className:"nice-development-studio__tag",children:d("devStudio.explorer.unsaved","Unsaved changes")})]},j.key))})},{id:"problems",label:`${d("devStudio.overview.problems","Problems")} (${i.length})`,content:i.length===0?e.jsx("p",{className:"nice-development-studio__muted",children:d("devStudio.overview.noProblems","No problems found.")}):e.jsx("ul",{className:"nice-development-studio__issues",children:i.map((j,$)=>{const M=A(j.path),b=j.messageKey?Object.entries(j.params??{}).reduce((E,[h,y])=>E.replace(`{${h}}`,String(y)),d(j.messageKey,j.message)):j.message;return e.jsxs("li",{className:`nice-development-studio__issue nice-development-studio__issue--${j.severity}`,children:[e.jsx(c.NiceIcon,{name:j.severity==="error"?"error":j.severity==="warning"?"warning":"info",size:14}),M?e.jsx(c.NiceButton,{size:"sm",variant:"ghost",onClick:()=>n(M.key),children:j.path}):j.path&&e.jsx("span",{className:"nice-development-studio__muted",children:j.path}),e.jsx("span",{children:b})]},$)})})},...r!=null&&r.listRevisions?[{id:"history",label:d("devStudio.overview.history","History"),content:e.jsx(c.NiceRevisionHistory,{revisions:v??[],language:"json",loadContent:r.readRevision?j=>r.readRevision(w,j):void 0,onRollback:r.rollback&&!s?async j=>{await r.rollback(w,j),await o.reload(w)}:void 0})}]:[],...l.map(j=>({id:`panel:${j.key}`,label:j.label,content:j.content}))];return e.jsxs("div",{className:"nice-development-studio__overview","data-testid":"studio-module-overview",children:[e.jsxs("div",{className:"nice-development-studio__doc-bar",children:[e.jsx(c.NiceIcon,{name:"box",size:16}),e.jsx("strong",{className:"nice-development-studio__doc-title",children:(a==null?void 0:a.label)??w.id}),e.jsx("span",{className:"nice-development-studio__muted",children:(a==null?void 0:a.location)??w.id}),(a==null?void 0:a.readOnly)&&e.jsx("span",{className:"nice-development-studio__tag",children:d("devStudio.explorer.readOnly","Read-only")}),(a==null?void 0:a.shadowedBy)&&e.jsx("span",{className:"nice-development-studio__tag",title:a.shadowedBy,children:d("devStudio.explorer.shadowed","shadowed")}),e.jsx("span",{className:"nice-development-studio__spacer"}),e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"check",size:14}),onClick:()=>void o.validate(w),"data-tour":"devstudio-validate",children:d("devStudio.validate","Validate")}),e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"refresh",size:14}),onClick:()=>void o.reload(w),children:d("devStudio.reload","Reload")}),!s&&e.jsxs(e.Fragment,{children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",disabled:!t.dirty,onClick:()=>o.discard(w),children:d("devStudio.discard","Discard changes")}),e.jsx(c.NiceButton,{size:"sm",variant:"primary",disabled:!t.dirty,onClick:m,"data-tour":"devstudio-save",children:t.dirty?d("devStudio.saveCount","Save ({count})").replace("{count}",String(t.changes.length)):d("devStudio.save","Save")})]})]}),!s&&R.length>0&&e.jsxs("div",{className:"nice-development-studio__row",children:[e.jsx("span",{className:"nice-development-studio__muted",children:d("devStudio.overview.newFile","New file:")}),R.map(j=>e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:j.icon??"file",size:14}),onClick:()=>{var M;const $=(M=u.newFile)==null?void 0:M.call(u,j.id,{key:w,files:t.working,documents:t.documents});$&&!t.working.some(b=>b.path===$.path)&&o.setRaw(w,$.path,$.text)},children:p(j)},j.id))]}),e.jsx(c.NiceTabs,{tabs:L})]})}const Et=t=>({type:"object",required:["id"],properties:{id:{type:"string",title:t("devStudio.template.id","Id (slug)")},category:{type:"string",title:t("devStudio.template.category","Category")},subCategory:{type:"string",title:t("devStudio.template.subCategory","Subcategory")},parentId:{type:"string",title:t("devStudio.template.parent","Parent template")},icon:{type:"string",title:t("devStudio.template.icon","Icon")},sortOrder:{type:"number",title:t("devStudio.template.sortOrder","Order")},tags:{type:"array",items:{type:"string"},title:t("devStudio.template.tags","Tags")}}});function Mt({session:t,template:a,locales:o,extraSchema:r,readOnly:u,onSaved:i,onDeleted:s}){var M;const{t:l}=c.useNiceTranslation(),[n,m]=g.useState(()=>a??{id:"",translations:{[o[0]??"en"]:{name:""}},modules:[]}),[d,p]=g.useState(null),v=u||!!(a!=null&&a.readOnly),k={id:n.id,category:n.category,subCategory:n.subCategory,parentId:n.parentId,icon:n.icon,sortOrder:n.sortOrder,tags:n.tags},w=Object.fromEntries(Object.entries(n.translations).map(([b,E])=>[b,{name:E.name,description:E.description??""}])),A=g.useMemo(()=>t.workspaces.map(b=>{const E=t.modulesByWs[b.id]??[],h=[...new Set(E.map(y=>y.packageId??""))].sort();return{id:`w:${b.id}`,label:b.label,kind:"workspace",children:h.map(y=>({id:`w:${b.id}/p:${y}`,label:y||l("devStudio.explorer.noPackage","No package"),kind:"package",children:E.filter(S=>(S.packageId??"")===y).map(S=>({id:`m:${S.id}`,label:S.label,kind:"module"}))}))}}),[t.workspaces,t.modulesByWs,l]),R=g.useMemo(()=>{const b=new Map;for(const E of Object.values(t.modulesByWs))for(const h of E)b.set(h.id,h.label);return b},[t.modulesByWs]),L=b=>m({...n,modules:b}),j=(b,E)=>{const h=[...n.modules],[y]=h.splice(b,1);h.splice(b+E,0,y),L(h)},$=[{field:"label",header:l("devStudio.explorer.name","Name")}];return e.jsxs("div",{className:"nice-development-studio__template","data-testid":"studio-template-editor",children:[e.jsxs("div",{className:"nice-development-studio__doc-bar",children:[e.jsx(c.NiceIcon,{name:"layers",size:14}),e.jsx("strong",{className:"nice-development-studio__doc-title",children:a?((M=n.translations.en)==null?void 0:M.name)||n.id:l("devStudio.template.new","New template")}),e.jsx("span",{className:"nice-development-studio__spacer"}),!v&&e.jsx(c.NiceButton,{size:"sm",variant:"primary",disabled:!n.id.trim(),onClick:async()=>{p(null);const b=await t.saveTemplate({...n,id:n.id.trim()},a==null?void 0:a.id);b?i==null||i(b):p(l("devStudio.template.saveFailed","The template could not be saved; see the output panel."))},children:l("devStudio.save","Save")}),!v&&a&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"trash",size:14}),onClick:async()=>{await t.deleteTemplate(a.id)&&(s==null||s())},children:l("devStudio.delete","Delete")})]}),d&&e.jsx("p",{className:"nice-development-studio__error",role:"alert",children:d}),e.jsxs("div",{className:"nice-development-studio__columns",children:[e.jsxs("section",{children:[e.jsx("h4",{children:l("devStudio.template.basics","Template")}),e.jsx(pe,{schema:Et(l),value:k,readOnly:v,onChange:b=>m({...n,id:String(b.id??""),category:b.category||void 0,subCategory:b.subCategory||void 0,parentId:b.parentId||void 0,icon:b.icon||void 0,sortOrder:typeof b.sortOrder=="number"?b.sortOrder:void 0,tags:Array.isArray(b.tags)?b.tags:void 0})}),r&&e.jsx(pe,{schema:r,value:n.extra??{},readOnly:v,onChange:b=>m({...n,extra:b})}),e.jsx("h4",{children:l("devStudio.template.translations","Name and description")}),e.jsx(Ce,{value:w,locales:[...new Set([...o,...Object.keys(w)])],allowEditLocales:!0,readOnly:v,onChange:b=>m({...n,translations:Object.fromEntries(Object.entries(b).map(([E,h])=>[E,{name:h.name??"",...h.description?{description:h.description}:{}}]))})})]}),e.jsxs("section",{children:[e.jsx("h4",{children:l("devStudio.template.modules","Modules")}),e.jsx(c.NiceTreeGrid,{data:A,nested:!0,keyField:"id",childrenField:"children",columns:$,sortable:!1,compact:!0,checkable:!0,checkStrategy:"leaves",isRowCheckable:b=>b.kind!=="workspace",isRowDisabled:()=>v,checkedKeys:n.modules.map(b=>`m:${b.moduleId}`),onCheckedChange:b=>{const E=b.filter(S=>S.startsWith("m:")).map(S=>S.slice(2)),h=n.modules.filter(S=>E.includes(S.moduleId)),y=E.filter(S=>!h.some(O=>O.moduleId===S)).map(S=>({moduleId:S}));L([...h,...y])},checkedSummary:b=>l("devStudio.template.summary","{count} modules · {required} required").replace("{count}",String(b.checked)).replace("{required}",String(n.modules.filter(E=>E.required).length)),searchable:!0,searchFields:["label"],virtualScroll:!0,height:320,"aria-label":l("devStudio.template.modules","Modules")}),e.jsxs("table",{className:"nice-development-studio__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:l("devStudio.template.module","Module")}),e.jsx("th",{children:l("devStudio.template.required","required")}),e.jsx("th",{children:l("devStudio.template.condition","Condition")}),!v&&e.jsx("th",{"aria-label":l("devStudio.template.order","Order")})]})}),e.jsx("tbody",{children:n.modules.map((b,E)=>e.jsxs("tr",{children:[e.jsx("td",{children:R.get(b.moduleId)??b.moduleId}),e.jsx("td",{children:e.jsx("input",{type:"checkbox",checked:!!b.required,disabled:v,"aria-label":`${l("devStudio.template.required","required")} ${b.moduleId}`,onChange:h=>L(n.modules.map((y,S)=>S===E?{...y,required:h.target.checked}:y))})}),e.jsx("td",{children:e.jsx("input",{className:"nice-development-studio__cell",value:b.condition??"",readOnly:v,"aria-label":`${l("devStudio.template.condition","Condition")} ${b.moduleId}`,onChange:h=>L(n.modules.map((y,S)=>S===E?{...y,condition:h.target.value||void 0}:y))})}),!v&&e.jsxs("td",{className:"nice-development-studio__nowrap",children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",disabled:E===0,ariaLabel:l("devStudio.template.up","Move up"),onClick:()=>j(E,-1),children:e.jsx(c.NiceIcon,{name:"chevron-up",size:12})}),e.jsx(c.NiceButton,{size:"sm",variant:"ghost",disabled:E===n.modules.length-1,ariaLabel:l("devStudio.template.down","Move down"),onClick:()=>j(E,1),children:e.jsx(c.NiceIcon,{name:"chevron-down",size:12})})]})]},b.moduleId))})]})]})]})]})}function $t({session:t,pkg:a,readOnly:o,onNewModule:r,onOpenModule:u}){const{t:i}=c.useNiceTranslation(),[s,l]=g.useState({id:a.id,label:a.label,description:a.description,icon:a.icon}),n=(t.modulesByWs[a.workspaceId]??[]).filter(d=>d.packageId===a.id),m=!o&&!a.derived&&!a.readOnly;return e.jsxs("div",{className:"nice-development-studio__template","data-testid":"studio-package-editor",children:[e.jsxs("div",{className:"nice-development-studio__doc-bar",children:[e.jsx(c.NiceIcon,{name:"archive",size:14}),e.jsx("strong",{className:"nice-development-studio__doc-title",children:a.label||a.id}),e.jsx("span",{className:"nice-development-studio__spacer"}),!o&&e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"plus",size:14}),onClick:r,children:i("devStudio.package.newModule","New module here")}),m&&e.jsx(c.NiceButton,{size:"sm",variant:"primary",onClick:()=>void t.savePackage({...a,id:String(s.id??a.id),label:String(s.label??""),description:s.description||void 0,icon:s.icon||void 0}),children:i("devStudio.save","Save")})]}),a.derived?e.jsx("p",{className:"nice-development-studio__muted",children:i("devStudio.package.derived","This package comes from the modules themselves (their category); rename it by changing their manifests.")}):e.jsx(pe,{schema:{type:"object",required:["id","label"],properties:{id:{type:"string",title:i("devStudio.package.id","Id")},label:{type:"string",title:i("devStudio.package.label","Name")},description:{type:"string",title:i("devStudio.package.description","Description")},icon:{type:"string",title:i("devStudio.template.icon","Icon")}}},value:s,readOnly:!m,onChange:d=>l(d)}),e.jsx("h4",{children:i("devStudio.template.modules","Modules")}),e.jsxs("ul",{className:"nice-development-studio__list",children:[n.map(d=>e.jsxs("li",{children:[e.jsx(c.NiceButton,{size:"sm",variant:"ghost",leftIcon:e.jsx(c.NiceIcon,{name:"box",size:14}),onClick:()=>u(d.id),children:d.label}),d.description&&e.jsx("span",{className:"nice-development-studio__muted",children:d.description})]},d.id)),n.length===0&&e.jsx("li",{className:"nice-development-studio__muted",children:i("devStudio.explorer.empty","No modules.")})]})]})}const Ft=[{target:".nice-development-studio",titleKey:"tutorial.devStudio.intro.title",title:"Development studio",contentKey:"tutorial.devStudio.intro.content",content:"Design whole modules: their manifest, entities, translations, views, workflows, permissions, data sources and seeds. Saving writes back only what changed.",placement:"auto"},{target:'[data-tour="devstudio-explorer"]',titleKey:"tutorial.devStudio.explorer.title",title:"Projects, packages and modules",contentKey:"tutorial.devStudio.explorer.content",content:"Browse projects, their packages and modules. Expand a module to see its files; switch to Templates to manage the module sets installed together.",placement:"right"},{target:".nice-development-studio .nice-console__tabs",titleKey:"tutorial.devStudio.tabs.title",title:"Open documents",contentKey:"tutorial.devStudio.tabs.content",content:"Each file opens in its own editor. Use Source to edit the raw text and Changes to see what saving writes.",placement:"bottom"},{target:'[data-tour="devstudio-save"]',titleKey:"tutorial.devStudio.save.title",title:"Validate and save",contentKey:"tutorial.devStudio.save.content",content:"Check the module, review the changed files and save them — only the bytes you changed are written.",placement:"bottom"},{target:'[data-tour="devstudio-output"]',titleKey:"tutorial.devStudio.output.title",title:"Output",contentKey:"tutorial.devStudio.output.content",content:"Loading, saving and validation are logged here.",placement:"top"}],Ot=["en","pl","de","fr","es","uk"],zt=g.forwardRef(function(a,o){const{provider:r,preset:u,defaultModule:i,defaultExplorerTab:s="modules",onModuleOpen:l,onSaved:n,onError:m,reviewBeforeSave:d=!0,scriptRunner:p,renderViewPreview:v,modulePanels:k,readOnly:w=!1,theme:A="light",height:R=720,explorerWidth:L=300,tutorial:j,className:$,style:M,id:b,testId:E,"data-testid":h}=a,{t:y}=c.useNiceTranslation(),S=g.useRef(null);g.useImperativeHandle(o,()=>S.current);const O=g.useMemo(()=>typeof u=="function"?u(y):u??P.nativeStudioPreset,[u,y]),V=g.useMemo(()=>O.locales??Ot,[O]),N=It(r,O,{locales:V,onError:m}),[J,X]=g.useState([]),[Q,K]=g.useState(""),[T,F]=g.useState(null),[H,G]=g.useState(0),ee=g.useCallback(f=>{var z;return(z=N.modulesByWs[f.workspaceId])==null?void 0:z.find(D=>D.id===f.id)},[N.modulesByWs]),te=f=>{var z;return((z=ee(f))==null?void 0:z.label)??f.id},ae=g.useMemo(()=>{const f={};for(const[z,D]of Object.entries(N.modules))f[z]=[...Ae(D,O),...N.serverIssues[z]??[]];return f},[N.modules,N.serverIssues,O]),_=g.useMemo(()=>Object.fromEntries(Object.entries(ae).map(([f,z])=>[f,z.filter(D=>D.severity==="error").length])),[ae]),I=g.useCallback(f=>{X(z=>z.some(D=>D.key===f.key)?z:[...z,f]),K(f.key)},[]),x=g.useCallback(async f=>{N.modules[Y(f)]||await N.openModule(f),I({key:`o:${Y(f)}`,kind:"overview",module:f}),l==null||l(f)},[N,I,l]),C=g.useCallback(async(f,z)=>{N.modules[Y(f)]||await N.openModule(f),I({key:`d:${Y(f)}::${z}`,kind:"document",module:f,docKey:z})},[N,I]),B=g.useRef(!1);g.useEffect(()=>{i&&!B.current&&N.modulesByWs[i.workspaceId]&&(B.current=!0,x(i))},[i,N.modulesByWs,x]);const q=J.find(f=>f.key===Q),W=q&&"module"in q?q.module:void 0,U=g.useCallback(async f=>{const z=N.modules[Y(f)];if(!(z!=null&&z.dirty)||w)return;if(d){F({kind:"review",module:f});return}const D=await N.save(f);D&&!D.ok?F({kind:"review",module:f,conflict:D}):D!=null&&D.ok&&(n==null||n(f,D))},[N,w,d,n]),oe=g.useRef(()=>{});oe.current=()=>{W&&U(W)},g.useEffect(()=>{const f=S.current;if(!f)return;const z=D=>{(D.ctrlKey||D.metaKey)&&!D.altKey&&D.key.toLowerCase()==="s"&&(D.preventDefault(),oe.current())};return f.addEventListener("keydown",z),()=>f.removeEventListener("keydown",z)},[]);const le=f=>{X(z=>{var ie;const D=z.filter(ce=>ce.key!==f);return Q===f&&K(((ie=D[D.length-1])==null?void 0:ie.key)??""),D})},Z=N.workspaces.filter(f=>!f.readOnly).map(f=>({id:f.id,label:f.label})),ge=f=>{var he;if(f.kind==="package")return e.jsx($t,{session:N,pkg:f.pkg,readOnly:w,onNewModule:()=>F({kind:"wizard",prefill:{workspaceId:f.pkg.workspaceId,packageId:f.pkg.id}}),onOpenModule:ne=>void x({workspaceId:f.pkg.workspaceId,id:ne})});if(f.kind==="template"){const ne=f.templateId?(he=N.templates)==null?void 0:he.find(de=>de.id===f.templateId):void 0;return e.jsx(Mt,{session:N,template:ne,locales:V,extraSchema:O.templateSchema,readOnly:w,onSaved:de=>{(!f.templateId||de.id!==f.templateId)&&(le(f.key),I({key:`t:${de.id}`,kind:"template",templateId:de.id}))},onDeleted:()=>le(f.key)},f.key)}const z=N.modules[Y(f.module)];if(!z)return e.jsx("p",{className:"nice-development-studio__muted",children:y("devStudio.loading","Loading…")});const D=ee(f.module),ie=w||!!(D!=null&&D.readOnly);if(f.kind==="overview")return e.jsx(Ct,{module:z,moduleRef:D,session:N,provider:r,preset:O,issues:ae[Y(f.module)]??[],readOnly:ie,panels:(k==null?void 0:k({module:f.module,files:z.working,dirty:z.dirty}))??[],onOpenDocument:ne=>void C(f.module,ne),onSave:()=>void U(f.module)});const ce=z.documents.find(ne=>ne.key===f.docKey);return ce?e.jsx(xt,{module:z,doc:ce,preset:O,session:N,locales:V,readOnly:ie,scriptRunner:p,renderViewPreview:v},f.key):e.jsx("p",{className:"nice-development-studio__muted",children:y("devStudio.doc.gone","This file is no longer in the module.")})},me=J.map(f=>{var he,ne,de;const z="module"in f?N.modules[Y(f.module)]:void 0,D=f.kind==="document"?z==null?void 0:z.documents.find(fe=>fe.key===f.docKey):void 0,ie=f.kind==="overview"?!!(z!=null&&z.dirty):f.kind==="document"&&D&&z?D.key in z.drafts||D.paths.some(fe=>fe in z.raw):!1,ce=f.kind==="overview"?te(f.module):f.kind==="document"?(D==null?void 0:D.label)??f.docKey:f.kind==="package"?f.pkg.label||f.pkg.id:f.templateId?((de=(ne=(he=N.templates)==null?void 0:he.find(fe=>fe.id===f.templateId))==null?void 0:ne.translations.en)==null?void 0:de.name)??f.templateId:y("devStudio.template.new","New template");return{key:f.key,label:ie?`${ce} •`:ce,closable:!0,icon:e.jsx(c.NiceIcon,{name:f.kind==="overview"?"box":f.kind==="package"?"archive":f.kind==="template"?"layers":(D==null?void 0:D.kind.icon)??"file",size:14}),render:()=>ge(f)}}),se=W?N.modules[Y(W)]:void 0,ye=W?ae[Y(W)]??[]:[],qe=[...W?[{key:"module",position:"left",label:te(W)},{key:"dirty",position:"left",label:se!=null&&se.dirty?y("devStudio.status.changed","{count} changed files").replace("{count}",String(se.changes.length)):y("devStudio.status.saved","Saved")},{key:"issues",position:"left",label:e.jsxs("span",{className:"nice-development-studio__status",children:[e.jsx(c.NiceIcon,{name:ye.length===0?"check":"warning",size:12}),ye.length===0?y("devStudio.status.valid","No problems"):y("devStudio.status.problems","{count} problems").replace("{count}",String(ye.length))]}),onClick:()=>W&&I({key:`o:${Y(W)}`,kind:"overview",module:W})}]:[],...N.busy?[{key:"busy",position:"right",label:y("devStudio.loading","Loading…")}]:[]],Re=[{key:"save",label:y("devStudio.save","Save"),shortcut:"Ctrl+S",disabled:!(se!=null&&se.dirty)||w},{key:"validate",label:y("devStudio.validate","Validate"),disabled:!W},{key:"refresh",label:y("devStudio.refresh","Refresh")},...r!=null&&r.createModule&&O.generateModule&&!w?[{key:"newModule",label:y("devStudio.explorer.newModule","Module")}]:[]],xe=(T==null?void 0:T.kind)==="review"?N.modules[Y(T.module)]:void 0,Ve=`nice-development-studio${$?` ${$}`:""}`;return e.jsxs("div",{ref:S,id:b,className:Ve,style:{height:R,...M},"data-testid":h??E,children:[e.jsx(c.NiceConsole,{className:"nice-development-studio__console",style:{height:"100%"},theme:A,tabs:me,activeTabKey:Q,onTabChange:K,onTabClose:le,commandPalette:Re,onCommand:f=>{f==="save"?oe.current():f==="validate"&&W?N.validate(W):f==="refresh"?N.refresh():f==="newModule"&&F({kind:"wizard",prefill:{}})},toolbar:e.jsxs("div",{className:"nice-development-studio__toolbar",children:[e.jsx("strong",{children:y("devStudio.title","Development studio")}),j&&e.jsx(c.NiceTutorialButton,{steps:c.resolveTutorial(j,Ft)})]}),sidePanel:e.jsx(Tt,{session:N,provider:r,canCreateModule:!!(r!=null&&r.createModule)&&!!O.generateModule,canDuplicateModule:!!(r!=null&&r.createModule)&&!!O.duplicateModule,issueCounts:_,defaultTab:s,readOnly:w,actions:{openModule:f=>void x(f),openDocument:(f,z)=>void C(f,z),openPackage:f=>I({key:`p:${f.workspaceId}/${f.id}`,kind:"package",pkg:f}),openTemplate:f=>I({key:`t:${f}`,kind:"template",templateId:f}),newModule:f=>F({kind:"wizard",prefill:f}),newPackage:f=>F({kind:"package",workspaceId:f}),newTemplate:()=>{G(f=>f+1),I({key:`t:new:${H+1}`,kind:"template",templateId:null})},duplicateModule:f=>F({kind:"duplicate",module:f}),deleteModule:f=>F({kind:"delete",module:f}),addToTemplate:f=>F({kind:"templates",module:f}),validateModule:f=>{(async()=>(N.modules[Y(f)]||await N.openModule(f),await N.validate(f)))()}}}),sidePanelWidth:L,bottomPanelHeight:120,statusItems:qe,bottomPanel:e.jsx("div",{"data-tour":"devstudio-output",className:"nice-development-studio__output",children:e.jsx(c.NiceLogConsole,{title:y("devStudio.output","Output"),entries:N.logs,onClear:N.clearLogs,maxHeight:"100%"})}),children:e.jsx("div",{className:"nice-development-studio__placeholder",children:r?y("devStudio.placeholder","Open a module, a package or a template from the explorer."):y("devStudio.noProvider","Connect a provider to browse modules.")})}),(T==null?void 0:T.kind)==="wizard"&&e.jsx(ht,{open:!0,onClose:()=>F(null),session:N,preset:O,locales:V,prefill:T.prefill,onCreated:f=>void x(f)}),(T==null?void 0:T.kind)==="review"&&xe&&e.jsx(ft,{open:!0,moduleLabel:te(T.module),changes:xe.changes,original:f=>{var z;return((z=xe.files.find(D=>D.path===f))==null?void 0:z.text)??""},conflict:T.conflict,onClose:()=>F(null),onSave:async()=>{const f=await N.save(T.module);f!=null&&f.ok?(F(null),n==null||n(T.module,f)):f&&F({...T,conflict:f})},onOverwrite:async()=>{const f=await N.save(T.module,{force:!0});f!=null&&f.ok&&(F(null),n==null||n(T.module,f))},onReload:async()=>{await N.reload(T.module),F(null)}}),(T==null?void 0:T.kind)==="delete"&&e.jsx(c.NiceConfirmDialog,{visible:!0,variant:"warning",header:y("devStudio.delete.title","Delete module"),message:y("devStudio.delete.message","Delete {module} and all its files?").replace("{module}",te(T.module)),acceptLabel:y("devStudio.delete","Delete"),rejectLabel:y("devStudio.cancel","Cancel"),onReject:()=>F(null),onAccept:async()=>{const f=T.module;F(null),await N.deleteModule(f)&&X(z=>z.filter(D=>!("module"in D)||Y(D.module)!==Y(f)))}}),(T==null?void 0:T.kind)==="duplicate"&&e.jsx(Fe,{open:!0,title:y("devStudio.duplicate.title","Duplicate {module}").replace("{module}",te(T.module)),workspaces:Z,workspaceId:Z.some(f=>f.id===T.module.workspaceId)?T.module.workspaceId:void 0,idLabel:y("devStudio.duplicate.id","New module id"),initialId:`${T.module.id}Copy`,onClose:()=>F(null),onSubmit:async f=>{var ie;const z=T.module;F(null);const D=await N.duplicateModule(z,{workspaceId:f.workspaceId,id:f.id,packageId:(ie=ee(z))==null?void 0:ie.packageId});D&&x({workspaceId:D.workspaceId,id:D.id})}}),(T==null?void 0:T.kind)==="package"&&e.jsx(Fe,{open:!0,title:y("devStudio.package.new","New package"),workspaces:Z,workspaceId:T.workspaceId,idLabel:y("devStudio.package.id","Id"),withLabel:!0,onClose:()=>F(null),onSubmit:async f=>{F(null);const z=await N.savePackage({id:f.id,workspaceId:f.workspaceId,label:f.label});z&&I({key:`p:${z.workspaceId}/${z.id}`,kind:"package",pkg:z})}}),(T==null?void 0:T.kind)==="templates"&&N.templates&&e.jsx(vt,{open:!0,moduleId:T.module.id,templates:N.templates,onClose:()=>F(null),onApply:async f=>{F(null);for(const z of f)await N.saveTemplate(z,z.id)}})]})});exports.arrayFileKind=P.arrayFileKind;exports.buildDocuments=P.buildDocuments;exports.createMemoryStudioProvider=P.createMemoryStudioProvider;exports.defineManifestSection=P.defineManifestSection;exports.deriveDefaultRbac=P.deriveDefaultRbac;exports.detectJsonTextFormat=P.detectJsonTextFormat;exports.encodeDocument=P.encodeDocument;exports.endsWithAny=P.endsWithAny;exports.entitiesToSchemas=P.entitiesToSchemas;exports.fileName=P.fileName;exports.fitManifestSection=P.fitManifestSection;exports.i18nFileKind=P.i18nFileKind;exports.itemsFileKind=P.itemsFileKind;exports.jsonFallbackKind=P.jsonFallbackKind;exports.jsonFileKind=P.jsonFileKind;exports.jsonValueFitsSchema=P.jsonValueFitsSchema;exports.jsonValuesEqual=P.jsonValuesEqual;exports.keepTextFormat=P.keepTextFormat;exports.manifestSectionKeys=P.manifestSectionKeys;exports.modulePrefix=P.modulePrefix;exports.nativeDataSourcesKind=P.nativeDataSourcesKind;exports.nativeEntitiesKind=P.nativeEntitiesKind;exports.nativeFileKinds=P.nativeFileKinds;exports.nativeHooksKind=P.nativeHooksKind;exports.nativeI18nKind=P.nativeI18nKind;exports.nativeManifestKind=P.nativeManifestKind;exports.nativeRbacKind=P.nativeRbacKind;exports.nativeStudioPreset=P.nativeStudioPreset;exports.nativeViewsKind=P.nativeViewsKind;exports.nativeWorkflowsKind=P.nativeWorkflowsKind;exports.objectFileKind=P.objectFileKind;exports.parseJsonText=P.parseJsonText;exports.patchJsonText=P.patchJsonText;exports.patchJsonTextDetailed=P.patchJsonTextDetailed;exports.readTranslations=P.readTranslations;exports.resolveFileKind=P.resolveFileKind;exports.safeJson=P.safeJson;exports.slugifyModuleId=P.slugifyModuleId;exports.stringifyJsonText=P.stringifyJsonText;exports.textFallbackKind=P.textFallbackKind;exports.writeTranslations=P.writeTranslations;exports.NiceArrayField=Be;exports.NiceDevelopmentStudio=zt;exports.NiceEntityEditor=Te;exports.NiceI18nEditor=Ce;exports.NiceSchemaForm=pe;exports.aiFormConfigToFormFields=He;exports.aiFormFieldType=Ke;exports.formBuilderSchemaToNiceFormItems=We;exports.formFieldsToFormItems=_e;exports.formSchemaToJsonSchema=Ze;exports.jsonSchemaToFormItems=we;exports.schemaToFormItems=Je;exports.validateAgainstJsonSchema=Ie;exports.validateFormSchema=Ue;