@superdoc-dev/template-builder 0.1.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +235 -0
- package/dist/defaults/FieldList.d.ts +4 -0
- package/dist/defaults/FieldList.d.ts.map +1 -0
- package/dist/defaults/FieldMenu.d.ts +3 -0
- package/dist/defaults/FieldMenu.d.ts.map +1 -0
- package/dist/defaults/index.d.ts +6 -0
- package/dist/defaults/index.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.mjs +1112 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +93 -0
package/README.md
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# @superdoc-dev/template-builder
|
|
2
|
+
|
|
3
|
+
React template building component for SuperDoc that enables document field management using structured content (SDT).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @superdoc-dev/template-builder
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
import SuperDocTemplateBuilder from '@superdoc-dev/template-builder';
|
|
15
|
+
import 'superdoc/dist/style.css';
|
|
16
|
+
|
|
17
|
+
function TemplateEditor() {
|
|
18
|
+
return (
|
|
19
|
+
<SuperDocTemplateBuilder
|
|
20
|
+
document={{
|
|
21
|
+
source: "template.docx",
|
|
22
|
+
mode: "editing"
|
|
23
|
+
}}
|
|
24
|
+
|
|
25
|
+
fields={{
|
|
26
|
+
available: [
|
|
27
|
+
{ id: 'customer_name', label: 'Customer Name', category: 'Contact' },
|
|
28
|
+
{ id: 'invoice_date', label: 'Invoice Date', category: 'Invoice' },
|
|
29
|
+
{ id: 'amount', label: 'Amount', category: 'Invoice' }
|
|
30
|
+
]
|
|
31
|
+
}}
|
|
32
|
+
|
|
33
|
+
onTrigger={(event) => {
|
|
34
|
+
console.log('User typed trigger at', event.position);
|
|
35
|
+
}}
|
|
36
|
+
|
|
37
|
+
onFieldInsert={(field) => {
|
|
38
|
+
console.log('Field inserted:', field.alias);
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## What You Receive
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
{
|
|
49
|
+
fields: [
|
|
50
|
+
{ id: "field_123", alias: "Customer Name", tag: "contact" },
|
|
51
|
+
{ id: "field_124", alias: "Invoice Date", tag: "invoice" }
|
|
52
|
+
],
|
|
53
|
+
document: { /* ProseMirror document JSON */ }
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **🎯 Trigger Detection** - Type `{{` (customizable) to insert fields
|
|
60
|
+
- **📝 Field Management** - Insert, update, delete, and navigate fields
|
|
61
|
+
- **🔍 Field Discovery** - Automatically finds existing fields in documents
|
|
62
|
+
- **🎨 UI Agnostic** - Bring your own menus, panels, and components
|
|
63
|
+
- **📄 SDT Based** - Uses structured content tags for Word compatibility
|
|
64
|
+
- **⚡ Simple API** - Clear callbacks for trigger events and field changes
|
|
65
|
+
|
|
66
|
+
## API
|
|
67
|
+
|
|
68
|
+
### Component Props
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
<SuperDocTemplateBuilder
|
|
72
|
+
// Document configuration
|
|
73
|
+
document={{
|
|
74
|
+
source: File | Blob | string,
|
|
75
|
+
mode: 'editing' | 'viewing'
|
|
76
|
+
}}
|
|
77
|
+
|
|
78
|
+
// Field configuration
|
|
79
|
+
fields={{
|
|
80
|
+
available: FieldDefinition[], // Fields user can insert
|
|
81
|
+
initial: TemplateField[] // Pre-existing fields
|
|
82
|
+
}}
|
|
83
|
+
|
|
84
|
+
// UI components (optional)
|
|
85
|
+
menu={{
|
|
86
|
+
trigger: '{{', // Trigger pattern
|
|
87
|
+
component: CustomFieldMenu // Custom menu component
|
|
88
|
+
}}
|
|
89
|
+
|
|
90
|
+
list={{
|
|
91
|
+
position: 'left' | 'right', // Sidebar position
|
|
92
|
+
component: CustomFieldList // Custom list component
|
|
93
|
+
}}
|
|
94
|
+
|
|
95
|
+
// Toolbar (optional)
|
|
96
|
+
toolbar={true} // Render built-in toolbar container
|
|
97
|
+
// toolbar="#my-toolbar" // Mount into existing element
|
|
98
|
+
// toolbar={{ // Configure built-in toolbar
|
|
99
|
+
// toolbarGroups: ['center'],
|
|
100
|
+
// excludeItems: ['italic', 'bold'],
|
|
101
|
+
// }}
|
|
102
|
+
|
|
103
|
+
// Event handlers
|
|
104
|
+
onReady={() => {}}
|
|
105
|
+
onTrigger={(event) => {}}
|
|
106
|
+
onFieldInsert={(field) => {}}
|
|
107
|
+
onFieldUpdate={(field) => {}}
|
|
108
|
+
onFieldDelete={(fieldId) => {}}
|
|
109
|
+
onFieldsChange={(fields) => {}}
|
|
110
|
+
onFieldSelect={(field) => {}}
|
|
111
|
+
/>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Ref Methods
|
|
115
|
+
|
|
116
|
+
```jsx
|
|
117
|
+
const ref = useRef();
|
|
118
|
+
|
|
119
|
+
// Insert fields
|
|
120
|
+
ref.current.insertField({ alias: 'Customer Name' });
|
|
121
|
+
ref.current.insertBlockField({ alias: 'Terms Block' });
|
|
122
|
+
|
|
123
|
+
// Update/delete fields
|
|
124
|
+
ref.current.updateField(fieldId, { alias: 'New Name' });
|
|
125
|
+
ref.current.deleteField(fieldId);
|
|
126
|
+
|
|
127
|
+
// Navigation
|
|
128
|
+
ref.current.selectField(fieldId);
|
|
129
|
+
ref.current.nextField(); // Tab behavior
|
|
130
|
+
ref.current.previousField(); // Shift+Tab behavior
|
|
131
|
+
|
|
132
|
+
// Get data
|
|
133
|
+
const fields = ref.current.getFields();
|
|
134
|
+
const template = await ref.current.exportTemplate();
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Custom Components
|
|
138
|
+
|
|
139
|
+
### Field Menu
|
|
140
|
+
|
|
141
|
+
```jsx
|
|
142
|
+
const CustomFieldMenu = ({ isVisible, position, availableFields, onSelect, onClose }) => {
|
|
143
|
+
if (!isVisible) return null;
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<div style={{ position: 'fixed', left: position?.left, top: position?.top }}>
|
|
147
|
+
{availableFields.map(field => (
|
|
148
|
+
<button key={field.id} onClick={() => onSelect(field)}>
|
|
149
|
+
{field.label}
|
|
150
|
+
</button>
|
|
151
|
+
))}
|
|
152
|
+
<button onClick={onClose}>Cancel</button>
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Field List
|
|
159
|
+
|
|
160
|
+
```jsx
|
|
161
|
+
const CustomFieldList = ({ fields, onSelect, onDelete, selectedFieldId }) => {
|
|
162
|
+
return (
|
|
163
|
+
<div>
|
|
164
|
+
<h3>Fields ({fields.length})</h3>
|
|
165
|
+
{fields.map(field => (
|
|
166
|
+
<div
|
|
167
|
+
key={field.id}
|
|
168
|
+
onClick={() => onSelect(field)}
|
|
169
|
+
style={{ background: selectedFieldId === field.id ? '#blue' : '#gray' }}
|
|
170
|
+
>
|
|
171
|
+
{field.alias}
|
|
172
|
+
<button onClick={() => onDelete(field.id)}>Delete</button>
|
|
173
|
+
</div>
|
|
174
|
+
))}
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Field Navigation
|
|
181
|
+
|
|
182
|
+
Enable Tab/Shift+Tab navigation:
|
|
183
|
+
|
|
184
|
+
```jsx
|
|
185
|
+
function TemplateEditor() {
|
|
186
|
+
const ref = useRef();
|
|
187
|
+
|
|
188
|
+
const handleKeyDown = (e) => {
|
|
189
|
+
if (e.key === 'Tab') {
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
if (e.shiftKey) {
|
|
192
|
+
ref.current?.previousField();
|
|
193
|
+
} else {
|
|
194
|
+
ref.current?.nextField();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div onKeyDown={handleKeyDown}>
|
|
201
|
+
<SuperDocTemplateBuilder ref={ref} {...props} />
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Export Template
|
|
208
|
+
|
|
209
|
+
Get the complete template data for saving:
|
|
210
|
+
|
|
211
|
+
```jsx
|
|
212
|
+
const handleSave = async () => {
|
|
213
|
+
await ref.current?.exportTemplate({ fileName: 'invoice.docx' });
|
|
214
|
+
};
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## TypeScript
|
|
218
|
+
|
|
219
|
+
Full TypeScript support included:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import SuperDocTemplateBuilder from '@superdoc-dev/template-builder';
|
|
223
|
+
import type {
|
|
224
|
+
TemplateField,
|
|
225
|
+
FieldDefinition,
|
|
226
|
+
TriggerEvent,
|
|
227
|
+
SuperDocTemplateBuilderHandle
|
|
228
|
+
} from '@superdoc-dev/template-builder';
|
|
229
|
+
|
|
230
|
+
const ref = useRef<SuperDocTemplateBuilderHandle>(null);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldList.d.ts","sourceRoot":"","sources":["../../src/defaults/FieldList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAsI9C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldMenu.d.ts","sourceRoot":"","sources":["../../src/defaults/FieldMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,UAAU,CAAC;AAEhE,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA8U9C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/defaults/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FieldMenu, FieldList } from './defaults';
|
|
2
|
+
import type * as Types from "./types";
|
|
3
|
+
export * from './types';
|
|
4
|
+
export { FieldMenu, FieldList };
|
|
5
|
+
declare const SuperDocTemplateBuilder: import('react').ForwardRefExoticComponent<Types.SuperDocTemplateBuilderProps & import('react').RefAttributes<Types.SuperDocTemplateBuilderHandle>>;
|
|
6
|
+
export default SuperDocTemplateBuilder;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,KAAK,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAElD,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAsFhC,QAAA,MAAM,uBAAuB,oJAmjB3B,CAAC;AAIH,eAAe,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";var Oe=Object.create;var xe=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var Ie=Object.getPrototypeOf,Me=Object.prototype.hasOwnProperty;var De=(s,d,f,u)=>{if(d&&typeof d=="object"||typeof d=="function")for(let r of Ae(d))!Me.call(s,r)&&r!==f&&xe(s,r,{get:()=>d[r],enumerable:!(u=Pe(d,r))||u.enumerable});return s};var Le=(s,d,f)=>(f=s!=null?Oe(Ie(s)):{},De(d||!s||!s.__esModule?xe(f,"default",{value:s,enumerable:!0}):f,s));Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const i=require("react");var ie={exports:{}},ne={};/**
|
|
2
|
+
* @license React
|
|
3
|
+
* react-jsx-runtime.production.js
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/var ge;function Be(){if(ge)return ne;ge=1;var s=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function f(u,r,l){var F=null;if(l!==void 0&&(F=""+l),r.key!==void 0&&(F=""+r.key),"key"in r){l={};for(var I in r)I!=="key"&&(l[I]=r[I])}else l=r;return r=l.ref,{$$typeof:s,type:u,key:F,ref:r!==void 0?r:null,props:l}}return ne.Fragment=d,ne.jsx=f,ne.jsxs=f,ne}var oe={};/**
|
|
10
|
+
* @license React
|
|
11
|
+
* react-jsx-runtime.development.js
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*/var be;function $e(){return be||(be=1,process.env.NODE_ENV!=="production"&&(function(){function s(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===le?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case O:return"Fragment";case E:return"Profiler";case Q:return"StrictMode";case b:return"Suspense";case C:return"SuspenseList";case D:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case U:return"Portal";case A:return e.displayName||"Context";case V:return(e._context.displayName||"Context")+".Consumer";case c:var a=e.render;return e=e.displayName,e||(e=a.displayName||a.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case T:return a=e.displayName||null,a!==null?a:s(e.type)||"Memo";case S:a=e._payload,e=e._init;try{return s(e(a))}catch{}}return null}function d(e){return""+e}function f(e){try{d(e);var a=!1}catch{a=!0}if(a){a=console;var x=a.error,p=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return x.call(a,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",p),d(e)}}function u(e){if(e===O)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===S)return"<...>";try{var a=s(e);return a?"<"+a+">":"<...>"}catch{return"<...>"}}function r(){var e=Z.A;return e===null?null:e.getOwner()}function l(){return Error("react-stack-top-frame")}function F(e){if(se.call(e,"key")){var a=Object.getOwnPropertyDescriptor(e,"key").get;if(a&&a.isReactWarning)return!1}return e.key!==void 0}function I(e,a){function x(){L||(L=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",a))}x.isReactWarning=!0,Object.defineProperty(e,"key",{get:x,configurable:!0})}function z(){var e=s(this.type);return ee[e]||(ee[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function H(e,a,x,p,$,re){var h=x.ref;return e={$$typeof:M,type:e,key:a,props:x,_owner:p},(h!==void 0?h:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:z}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:$}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:re}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function P(e,a,x,p,$,re){var h=a.children;if(h!==void 0)if(p)if(K(h)){for(p=0;p<h.length;p++)N(h[p]);Object.freeze&&Object.freeze(h)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else N(h);if(se.call(a,"key")){h=s(e);var j=Object.keys(a).filter(function(ce){return ce!=="key"});p=0<j.length?"{key: someKey, "+j.join(": ..., ")+": ...}":"{key: someKey}",q[h+p]||(j=0<j.length?"{"+j.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
18
|
+
let props = %s;
|
|
19
|
+
<%s {...props} />
|
|
20
|
+
React keys must be passed directly to JSX without using spread:
|
|
21
|
+
let props = %s;
|
|
22
|
+
<%s key={someKey} {...props} />`,p,h,j,h),q[h+p]=!0)}if(h=null,x!==void 0&&(f(x),h=""+x),F(a)&&(f(a.key),h=""+a.key),"key"in a){x={};for(var J in a)J!=="key"&&(x[J]=a[J])}else x=a;return h&&I(x,typeof e=="function"?e.displayName||e.name||"Unknown":e),H(e,h,x,r(),$,re)}function N(e){k(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===S&&(e._payload.status==="fulfilled"?k(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function k(e){return typeof e=="object"&&e!==null&&e.$$typeof===M}var Y=i,M=Symbol.for("react.transitional.element"),U=Symbol.for("react.portal"),O=Symbol.for("react.fragment"),Q=Symbol.for("react.strict_mode"),E=Symbol.for("react.profiler"),V=Symbol.for("react.consumer"),A=Symbol.for("react.context"),c=Symbol.for("react.forward_ref"),b=Symbol.for("react.suspense"),C=Symbol.for("react.suspense_list"),T=Symbol.for("react.memo"),S=Symbol.for("react.lazy"),D=Symbol.for("react.activity"),le=Symbol.for("react.client.reference"),Z=Y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,se=Object.prototype.hasOwnProperty,K=Array.isArray,R=console.createTask?console.createTask:function(){return null};Y={react_stack_bottom_frame:function(e){return e()}};var L,ee={},B=Y.react_stack_bottom_frame.bind(Y,l)(),te=R(u(l)),q={};oe.Fragment=O,oe.jsx=function(e,a,x){var p=1e4>Z.recentlyCreatedOwnerStacks++;return P(e,a,x,!1,p?Error("react-stack-top-frame"):B,p?R(u(e)):te)},oe.jsxs=function(e,a,x){var p=1e4>Z.recentlyCreatedOwnerStacks++;return P(e,a,x,!0,p?Error("react-stack-top-frame"):B,p?R(u(e)):te)}})()),oe}var he;function We(){return he||(he=1,process.env.NODE_ENV==="production"?ie.exports=Be():ie.exports=$e()),ie.exports}var o=We();const Ee=({isVisible:s,position:d,availableFields:f,filteredFields:u,filterQuery:r,allowCreate:l,onSelect:F,onClose:I,onCreateField:z})=>{const[H,P]=i.useState(!1),[N,k]=i.useState("");i.useEffect(()=>{s||(P(!1),k(""))},[s]);const Y=i.useMemo(()=>({position:"absolute",left:d?.left,top:d?.top,zIndex:1e3,background:"white",border:"1px solid #ddd",borderRadius:"4px",boxShadow:"0 2px 8px rgba(0,0,0,0.1)",padding:"8px 0",minWidth:"200px"}),[d]),M=u??f,U=!!r,O=i.useMemo(()=>{const c=[],b=new Map;return M.forEach(C=>{const T=C.category?.trim()||"Uncategorized",S=b.get(T);if(S!==void 0){c[S].fields.push(C);return}b.set(T,c.length),c.push({category:T,fields:[C]})}),c},[M]),[Q,E]=i.useState({});i.useEffect(()=>{E(c=>{if(O.length===0)return Object.keys(c).length===0?c:{};const b={};let C=Object.keys(c).length!==O.length;return O.forEach(({category:T},S)=>{const D=U?!0:c[T]??S===0;b[T]=D,!C&&c[T]!==D&&(C=!0)}),C?b:c})},[O,U]);const V=i.useCallback(c=>{E(b=>({...b,[c]:!b[c]}))},[]);if(!s)return null;const A=async()=>{const c=N.trim();if(!c)return;const b={id:`custom_${Date.now()}`,label:c,category:"Custom"};try{if(z){const C=await z(b);F(C||b)}else F(b)}finally{P(!1),k("")}};return o.jsxs("div",{className:"superdoc-field-menu",style:Y,children:[U&&o.jsx("div",{style:{padding:"8px 16px",borderBottom:"1px solid #f0f0f0",marginBottom:"4px"},children:o.jsxs("div",{style:{fontSize:"12px",color:"#6b7280"},children:["Filtering results for",o.jsx("span",{style:{fontWeight:600,color:"#111827",marginLeft:"4px"},children:r})]})}),l&&!H&&o.jsx("div",{className:"field-menu-item",onClick:()=>P(!0),style:{padding:"8px 16px",cursor:"pointer",color:"#0066cc",fontWeight:500},children:"+ Create New Field"}),l&&H&&o.jsxs("div",{style:{padding:"8px 16px"},children:[o.jsx("input",{type:"text",value:N,placeholder:"Field name...",onChange:c=>k(c.target.value),onKeyDown:c=>{c.key==="Enter"&&A(),c.key==="Escape"&&(P(!1),k(""))},autoFocus:!0,style:{width:"100%",padding:"4px 8px",border:"1px solid #ddd",borderRadius:"3px"}}),o.jsxs("div",{style:{marginTop:"8px",display:"flex",gap:"8px"},children:[o.jsx("button",{onClick:A,disabled:!N.trim(),style:{padding:"4px 12px",background:N.trim()?"#0066cc":"#ccc",color:"white",border:"none",borderRadius:"3px",cursor:N.trim()?"pointer":"not-allowed"},children:"Create"}),o.jsx("button",{onClick:()=>{P(!1),k("")},style:{padding:"4px 12px",background:"white",border:"1px solid #ddd",borderRadius:"3px",cursor:"pointer"},children:"Cancel"})]})]}),l&&f.length>0&&o.jsx("div",{style:{borderTop:"1px solid #eee",margin:"4px 0"}}),O.length===0?o.jsx("div",{style:{padding:"16px",fontSize:"13px",color:"#6b7280",textAlign:"center"},children:"No matching fields"}):O.map(({category:c,fields:b},C)=>{const T=!!Q[c],S=`${Math.max(b.length*40,0)}px`;return o.jsxs("div",{style:{borderTop:C===0&&l?void 0:"1px solid #f0f0f0"},children:[o.jsxs("button",{type:"button",onClick:()=>V(c),style:{width:"100%",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 16px",background:"transparent",border:"none",cursor:"pointer",fontWeight:500,textAlign:"left"},children:[o.jsxs("span",{children:[c," (",b.length,")"]}),o.jsx("span",{"aria-hidden":!0,style:{display:"inline-block",width:"8px",height:"8px",borderRight:"2px solid #666",borderBottom:"2px solid #666",transform:T?"rotate(45deg)":"rotate(-45deg)",transition:"transform 0.2s ease",marginLeft:"12px"}})]}),o.jsx("div",{"data-category":c,"aria-hidden":!T,style:{overflow:"hidden",maxHeight:T?S:"0px",opacity:T?1:0,transition:"max-height 0.2s ease, opacity 0.2s ease",pointerEvents:T?"auto":"none"},children:o.jsx("div",{style:{padding:T?"4px 0":0},children:b.map(D=>o.jsx("div",{className:"field-menu-item",onClick:()=>F(D),style:{padding:"8px 16px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"space-between"},children:o.jsx("span",{style:{fontWeight:500},children:D.label})},D.id))})})]},c)}),o.jsx("div",{style:{borderTop:"1px solid #eee",marginTop:"4px"},children:o.jsx("button",{onClick:I,style:{width:"100%",padding:"6px 16px",background:"#f3f4f6",border:"none",borderRadius:"0 0 4px 4px",cursor:"pointer"},children:"Close"})})]})},Ce=({fields:s,onSelect:d,onDelete:f,selectedFieldId:u})=>o.jsxs("div",{className:"superdoc-field-list",style:{width:"250px",background:"white",border:"1px solid #e5e7eb",borderRadius:"8px",padding:"16px"},children:[o.jsxs("h3",{style:{margin:"0 0 16px 0",fontSize:"16px",fontWeight:"600"},children:["Template Fields (",s.length,")"]}),s.length===0?o.jsxs("div",{style:{color:"#9ca3af",fontSize:"14px",textAlign:"center",padding:"20px 0"},children:["No fields yet. Type ","{{"," to add a field."]}):o.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:s.map(r=>o.jsxs("div",{onClick:()=>d(r),style:{position:"relative",padding:"12px",background:u===r.id?"#eff6ff":"#f9fafb",border:u===r.id?"1px solid #3b82f6":"1px solid #e5e7eb",borderRadius:"6px",cursor:"pointer",transition:"all 0.2s"},onMouseEnter:l=>{u!==r.id&&(l.currentTarget.style.background="#f3f4f6")},onMouseLeave:l=>{u!==r.id&&(l.currentTarget.style.background="#f9fafb")},title:r.alias,children:[o.jsx("button",{onClick:l=>{l.stopPropagation(),f(r.id)},style:{position:"absolute",top:"8px",right:"8px",padding:"4px",background:"transparent",border:"none",cursor:"pointer",color:"#9ca3af",transition:"color 0.2s",display:"flex",alignItems:"center",justifyContent:"center"},onMouseEnter:l=>{l.currentTarget.style.color="#ef4444"},onMouseLeave:l=>{l.currentTarget.style.color="#9ca3af"},title:"Delete field",children:o.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:o.jsx("path",{d:"M6 2V1.5C6 1.22386 6.22386 1 6.5 1H9.5C9.77614 1 10 1.22386 10 1.5V2M2 4H14M12.6667 4L12.1991 11.0129C12.129 12.065 12.0939 12.5911 11.8667 12.99C11.6666 13.3412 11.3648 13.6235 11.0011 13.7998C10.588 14 10.0607 14 9.00623 14H6.99377C5.93927 14 5.41202 14 4.99889 13.7998C4.63517 13.6235 4.33339 13.3412 4.13332 12.99C3.90607 12.5911 3.871 12.065 3.80086 11.0129L3.33333 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),o.jsxs("div",{style:{paddingRight:"24px"},children:[o.jsx("div",{style:{fontWeight:"500",fontSize:"14px",marginBottom:r.alias&&r.alias!==r.id?"4px":"0"},children:r.id}),r.alias&&r.alias!==r.id&&o.jsx("div",{style:{fontSize:"12px",color:"#4b5563"},children:r.alias})]})]},r.id))})]}),ye=s=>{const d=s.helpers?.structuredContentCommands;return d?.getStructuredContentTags?(d.getStructuredContentTags(s.state)||[]).map(u=>{const l=(u?.node??u)?.attrs??{};return{id:l.id,alias:l.alias||l.label||"",tag:l.tag}}).filter(u=>!!u.id):[]},ve=(s,d)=>{if(s===d)return!0;if(s.length!==d.length)return!1;for(let f=0;f<s.length;f+=1){const u=s[f],r=d[f];if(!r||u.id!==r.id||u.alias!==r.alias||u.tag!==r.tag||u.position!==r.position)return!1}return!0},Ye=s=>{if(!s)return null;if(s===!0)return{selector:"#superdoc-toolbar",config:{},renderDefaultContainer:!0};if(typeof s=="string")return{selector:s,config:{},renderDefaultContainer:!1};const{selector:d,...f}=s;return{selector:d||"#superdoc-toolbar",config:f,renderDefaultContainer:d===void 0}},Re=i.forwardRef((s,d)=>{const{document:f,fields:u={},menu:r={},list:l={},toolbar:F,onReady:I,onTrigger:z,onFieldInsert:H,onFieldUpdate:P,onFieldDelete:N,onFieldsChange:k,onFieldSelect:Y,onFieldCreate:M,className:U,style:O,documentHeight:Q="600px"}=s,[E,V]=i.useState(u.initial||[]),[A,c]=i.useState(null),[b,C]=i.useState(!1),[T,S]=i.useState(),[D,le]=i.useState(""),[Z,se]=i.useState(()=>u.available||[]),K=i.useRef(null),R=i.useRef(null),L=i.useRef(null),ee=i.useRef(u);ee.current=u;const B=i.useRef(null),te=i.useRef(b);i.useEffect(()=>{te.current=b},[b]);const q=r.trigger||"{{",e=ee.current.available||[],a=i.useCallback(t=>{const n=t.trim().toLowerCase();return n?e.filter(y=>{const v=y.label.toLowerCase(),_=y.category?.toLowerCase()||"";return v.includes(n)||_.includes(n)}):e},[e]),x=i.useCallback(t=>{le(t),se(a(t))},[a]),p=i.useCallback(()=>{x("")},[x]),$=i.useCallback((t,n)=>{if(!R.current?.activeEditor)return!1;const y=R.current.activeEditor,v=`field_${Date.now()}`,_=t==="inline"?y.commands.insertStructuredContentInline?.({attrs:{id:v,alias:n.alias,tag:n.metadata?JSON.stringify(n.metadata):n.category},text:n.defaultValue||n.alias}):y.commands.insertStructuredContentBlock?.({attrs:{id:v,alias:n.alias,tag:n.metadata?JSON.stringify(n.metadata):n.category},text:n.defaultValue||n.alias});if(_){const w={id:v,alias:n.alias,tag:n.category};V(g=>{const m=[...g,w];return k?.(m),m}),H?.(w)}return _},[H,k]),re=i.useCallback((t,n)=>{if(!R.current?.activeEditor)return!1;const v=R.current.activeEditor.commands.updateStructuredContentById?.(t,{attrs:n});return v&&V(_=>{const w=_.map(m=>m.id===t?{...m,...n}:m);k?.(w);const g=w.find(m=>m.id===t);return g&&P?.(g),w}),v},[P,k]),h=i.useCallback(t=>{const n=R.current?.activeEditor;if(!n){console.warn("[SuperDocTemplateBuilder] deleteField called without active editor");let g=!1;return V(m=>{if(!m.some(W=>W.id===t))return m;const X=m.filter(W=>W.id!==t);return g=!0,k?.(X),X}),g&&(N?.(t),c(m=>m===t?null:m)),g}let y=!1;try{y=n.commands.deleteStructuredContentById?.(t)??!1}catch(g){console.error("[SuperDocTemplateBuilder] Delete command failed:",g)}let v=ye(n);const _=v.some(g=>g.id===t);!y&&_&&(v=v.filter(g=>g.id!==t));let w=!1;return V(g=>{if(ve(g,v))return g;const m=g.some(W=>W.id===t),X=v.some(W=>W.id===t);return m&&!X&&(w=!0),k?.(v),v}),w&&(N?.(t),c(g=>g===t?null:g)),y||w},[N,k]),j=i.useCallback(t=>{if(!R.current?.activeEditor)return;R.current.activeEditor.commands.selectStructuredContentById?.(t),c(t);const y=E.find(v=>v.id===t);y&&Y?.(y)},[E,Y]),J=i.useCallback(t=>{if(!t)return;const n=ye(t);V(y=>ve(y,n)?y:(k?.(n),n))},[k]);i.useEffect(()=>K.current?((async()=>{const{SuperDoc:n}=await import("superdoc"),y={selector:K.current,document:f?.source,documentMode:f?.mode||"editing",onReady:()=>{if(v.activeEditor){const _=v.activeEditor;_.on("update",({editor:w})=>{const{state:g}=w,{from:m}=g.selection;if(m>=q.length){const ue=m-q.length;if(g.doc.textBetween(ue,m)===q){const fe=w.view.coordsAtPos(m),pe=new DOMRect(fe.left,fe.top,0,0),me=()=>{const ae=R.current?.activeEditor;if(!ae)return;const Fe=ae.state.selection.from,Ne=ae.state.tr.delete(ue,Fe);ae.view.dispatch(Ne)};L.current=me,B.current=m,S(pe),C(!0),p(),z?.({position:{from:ue,to:m},bounds:pe,cleanup:me});return}}if(!te.current)return;if(B.current==null){C(!1),p();return}if(m<B.current){C(!1),B.current=null,p();return}const X=g.doc.textBetween(B.current,m);x(X);const W=w.view.coordsAtPos(m),_e=new DOMRect(W.left,W.top,0,0);S(_e)}),_.on("update",()=>{J(_)}),J(_)}I?.()}},v=new n({...y,...G&&{toolbar:G.selector,modules:{toolbar:{selector:G.selector,toolbarGroups:G.config.toolbarGroups||["center"],excludeItems:G.config.excludeItems||[],...G.config}}}});R.current=v})(),()=>{R.current&&(typeof R.current.destroy=="function"&&R.current.destroy(),R.current=null)}):void 0,[f?.source,f?.mode,q,J,I,z,F]);const ce=i.useCallback(async t=>{if(L.current&&(L.current(),L.current=null),B.current=null,p(),t.id.startsWith("custom_")&&M)try{const n=await M(t);if(n){$("inline",{alias:n.label,category:n.category,metadata:n.metadata,defaultValue:n.defaultValue}),C(!1);return}}catch(n){console.error("Field creation failed:",n)}$("inline",{alias:t.label,category:t.category,metadata:t.metadata,defaultValue:t.defaultValue}),C(!1)},[$,M,p]),ke=i.useCallback(()=>{C(!1),B.current=null,p(),L.current&&(L.current(),L.current=null)},[p]),Te=i.useCallback(()=>{if(!R.current?.activeEditor||E.length===0)return;const t=E.findIndex(y=>y.id===A),n=t>=0?(t+1)%E.length:0;j(E[n].id)},[E,A,j]),je=i.useCallback(()=>{if(!R.current?.activeEditor||E.length===0)return;const t=E.findIndex(y=>y.id===A),n=t>0?t-1:E.length-1;j(E[n].id)},[E,A,j]),we=i.useCallback(async t=>{try{await R.current?.export({exportType:["docx"],exportedName:t?.fileName?t?.fileName:"document"})}catch(n){throw console.error("Failed to export DOCX",n),n}},[]);i.useImperativeHandle(d,()=>({insertField:t=>$("inline",t),insertBlockField:t=>$("block",t),updateField:re,deleteField:h,selectField:j,nextField:Te,previousField:je,getFields:()=>E,exportTemplate:we}));const Se=r.component||Ee,de=l.component||Ce,G=Ye(F);return o.jsxs("div",{className:`superdoc-template-builder ${U||""}`,style:O,children:[o.jsxs("div",{style:{display:"flex",gap:"20px"},children:[l.position==="left"&&o.jsx("div",{className:"superdoc-template-builder-sidebar",children:o.jsx(de,{fields:E,onSelect:t=>j(t.id),onDelete:h,selectedFieldId:A||void 0})}),o.jsxs("div",{className:"superdoc-template-builder-document",style:{flex:1},children:[G?.renderDefaultContainer&&o.jsx("div",{id:"superdoc-toolbar",className:"superdoc-template-builder-toolbar","data-testid":"template-builder-toolbar"}),o.jsx("div",{ref:K,className:"superdoc-template-builder-editor",style:{height:Q},"data-testid":"template-builder-editor"})]}),l.position==="right"&&o.jsx("div",{className:"superdoc-template-builder-sidebar",children:o.jsx(de,{fields:E,onSelect:t=>j(t.id),onDelete:h,selectedFieldId:A||void 0})})]}),o.jsx(Se,{isVisible:b,position:T,availableFields:u.available||[],filteredFields:Z,filterQuery:D,allowCreate:u.allowCreate||!1,onSelect:ce,onClose:ke,onCreateField:M})]})});Re.displayName="SuperDocTemplateBuilder";exports.FieldList=Ce;exports.FieldMenu=Ee;exports.default=Re;
|