@scaleflex/template-builder 0.4.1 → 0.4.2
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.
|
@@ -12,7 +12,7 @@ metadata:
|
|
|
12
12
|
- design-templates
|
|
13
13
|
- web-component
|
|
14
14
|
status: ready
|
|
15
|
-
version:
|
|
15
|
+
version: 2
|
|
16
16
|
---
|
|
17
17
|
|
|
18
18
|
# Scaleflex Template Builder Integration Skill
|
|
@@ -24,6 +24,10 @@ metadata:
|
|
|
24
24
|
- User asks how to use `@scaleflex/template-builder` in their project
|
|
25
25
|
- User wants a banner / creative editor backed by Scaleflex rendering
|
|
26
26
|
|
|
27
|
+
A complete working React host (gallery, save round trip, live render
|
|
28
|
+
preview) is published at <https://stackblitz.com/edit/sotacrwx> — read its
|
|
29
|
+
`App.tsx` for the whole contract in one file.
|
|
30
|
+
|
|
27
31
|
## Step 1 — Decide who stores the template
|
|
28
32
|
|
|
29
33
|
This is the first question, and it changes everything downstream. Ask if it is
|
|
@@ -43,7 +47,7 @@ storage and does not want to map them onto Scaleflex tenants. Pick
|
|
|
43
47
|
Statelessness applies to the **document only**. The editor still needs an
|
|
44
48
|
authenticated Scaleflex tenant for server-side text rendering, custom fonts,
|
|
45
49
|
asset browsing, and metadata variables — so a stateless embed still needs a
|
|
46
|
-
credential (Step
|
|
50
|
+
credential (Step 8).
|
|
47
51
|
|
|
48
52
|
## Step 2 — Detect the target framework
|
|
49
53
|
|
|
@@ -213,7 +217,46 @@ try {
|
|
|
213
217
|
|
|
214
218
|
The React wrapper does this from what `onSave` returns or throws.
|
|
215
219
|
|
|
216
|
-
## Step 6 —
|
|
220
|
+
## Step 6 — Render links and previews (optional): `dam-store`
|
|
221
|
+
|
|
222
|
+
The CDN renders only files it stores, so a stateless host that wants image
|
|
223
|
+
URLs out of its templates (previews, production banners) needs a copy in
|
|
224
|
+
Filerobot too. Set `dam-store` and the element uploads that copy itself on
|
|
225
|
+
every save, before the `save` event fires — the host writes no upload code:
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<sfx-template-builder stateless dam-store store-folder="/my-app" …>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
builder.addEventListener('save', (e) => {
|
|
233
|
+
const { content, templateQuery, stored, storeError } = e.detail
|
|
234
|
+
// stored = { uuid, url } — append templateQuery to url and it IS an image:
|
|
235
|
+
// <img src=`${stored.url}&${templateQuery}&force_format=png`>
|
|
236
|
+
// storeError replaces stored when the copy failed; the raw content
|
|
237
|
+
// arrives either way — whether that fails the save is your confirmSave call.
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Wiring rules that matter:
|
|
242
|
+
|
|
243
|
+
- **Branch on the detail** (`'stored' in e.detail || 'storeError' in e.detail`),
|
|
244
|
+
never on the live `damStore` property — saves arrive from a serialized
|
|
245
|
+
upload queue and the property can change before a queued event lands.
|
|
246
|
+
- **Persist `stored.uuid` and pass it back as `stored-uuid` / `storedUuid`
|
|
247
|
+
(or the `storedUuid` field of `load()`) when reopening the template.** The
|
|
248
|
+
element's memory of its copy dies with the page; the seed is what lets a
|
|
249
|
+
re-save version the existing file in place instead of erroring on
|
|
250
|
+
unchanged content. Do NOT echo the uuid into `template-id` — an id change
|
|
251
|
+
deliberately reloads the editor.
|
|
252
|
+
- **A save can arrive after `close`** when its upload is still in flight —
|
|
253
|
+
keep the `save` listener attached until it does. Removing the element from
|
|
254
|
+
the DOM flushes pending saves to still-attached listeners immediately.
|
|
255
|
+
- The credential needs **upload rights**, or every save reports `storeError`.
|
|
256
|
+
- `store-folder` names where templates with no existing DAM file land; an
|
|
257
|
+
existing file's own folder always wins.
|
|
258
|
+
|
|
259
|
+
## Step 7 — Guard against losing edits
|
|
217
260
|
|
|
218
261
|
Assigning a new `content` / `templateId` / `templateName` / `templateQuery`
|
|
219
262
|
reloads the editor and
|
|
@@ -229,7 +272,7 @@ builder.addEventListener('dirtychange', (e) => {
|
|
|
229
272
|
Re-assigning an identical template is a no-op, so an unrelated re-render cannot
|
|
230
273
|
destroy work by accident.
|
|
231
274
|
|
|
232
|
-
## Step
|
|
275
|
+
## Step 8 — Authentication
|
|
233
276
|
|
|
234
277
|
Two credentials work. Both are minted **server-side** and injected into the
|
|
235
278
|
page; neither belongs in a public bundle.
|
|
@@ -278,7 +321,7 @@ server-side, so it authenticates on the handed-over credential and returns
|
|
|
278
321
|
template is what authorizes it when there is no Hub session. Full explanation:
|
|
279
322
|
*Why the editor still calls a server* in the README.
|
|
280
323
|
|
|
281
|
-
## Step
|
|
324
|
+
## Step 9 — Register the embedding origin (required)
|
|
282
325
|
|
|
283
326
|
The host page's origin must be in the deployment's embedding allowlist, via
|
|
284
327
|
`NEXT_PUBLIC_TRUSTED_HUB_ORIGINS` on the `design-templates-app` deployment.
|
|
@@ -288,7 +331,7 @@ This is baked in at build time, so it needs a redeploy.
|
|
|
288
331
|
and the widget reports `error` with code `handshake-timeout`. That is the
|
|
289
332
|
single most common first-integration failure — check it before anything else.
|
|
290
333
|
|
|
291
|
-
## Step
|
|
334
|
+
## Step 10 — Theming (optional)
|
|
292
335
|
|
|
293
336
|
```html
|
|
294
337
|
<sfx-template-builder brand-color="#FF6600" theme="dark" ...>
|
|
@@ -312,7 +355,7 @@ template document.
|
|
|
312
355
|
| `token` | yes | Scaleflex token (`ftoken`) |
|
|
313
356
|
| `sass-key` / `sassKey` | session auth | Project sass key |
|
|
314
357
|
| `session-uuid` / `sessionUuid` | session auth | Hub session uuid |
|
|
315
|
-
| `sec-template` / `secTemplate` | guest auth | Security-template key, instead of sass key + session uuid. Stateless only (Step
|
|
358
|
+
| `sec-template` / `secTemplate` | guest auth | Security-template key, instead of sass key + session uuid. Stateless only (Step 8) |
|
|
316
359
|
| `company-uuid`, `project-uuid` | no | Company / project scoping (session auth only) |
|
|
317
360
|
| `template-id` / `templateId` | no | DAM: the file uuid. Stateless: opaque host id |
|
|
318
361
|
| `mode` | no | `inline` (default) or `modal` (starts closed — call `open()`) |
|
|
@@ -321,7 +364,12 @@ template document.
|
|
|
321
364
|
| `new-template` / `newTemplate` | no | Stateless: open on a new, empty template — the widget supplies the blank document. Ignored when `content` is set |
|
|
322
365
|
| `template-name` / `templateName` | no | Stateless: header title |
|
|
323
366
|
| `template-query` / `templateQuery` | no | Stateless: the render to open on — the `templateQuery` from the last save. Empty uses the XML's `default=` values. |
|
|
324
|
-
| `
|
|
367
|
+
| `dam-store` / `damStore` | no | Stateless: store each save in Filerobot too; the `save` detail gains `stored: { uuid, url }` or `storeError` (Step 6) |
|
|
368
|
+
| `store-folder` / `storeFolder` | no | `dam-store`: folder for templates with no existing DAM file (default `/`) |
|
|
369
|
+
| `stored-uuid` / `storedUuid` | no | `dam-store`: the persisted `stored.uuid`, passed back so re-saves version the existing copy across reloads (Step 6) |
|
|
370
|
+
| `custom-metadata` / `customMetadata` | no | Metadata model offered as the **Custom metadata** value source: `[{ key, title?, group? }]` — names only, values go into the render query as `$slug=value` |
|
|
371
|
+
| `custom-metadata-label` / `customMetadataLabel` | no | Renames that value source in the editor's UI (wording only) |
|
|
372
|
+
| `brand-color`, `theme` | no | See Step 10 |
|
|
325
373
|
| `ready-timeout` / `readyTimeout` | no | Ms before `handshake-timeout` (default 20000) |
|
|
326
374
|
|
|
327
375
|
## Events Reference
|
|
@@ -330,26 +378,27 @@ template document.
|
|
|
330
378
|
|---|---|
|
|
331
379
|
| `ready` | — (editor mounted, auth valid) |
|
|
332
380
|
| `open` | — |
|
|
333
|
-
| `save` | `{ uuid, name }` (DAM) or `{ templateId, content, name, templateQuery }` (stateless) |
|
|
381
|
+
| `save` | `{ uuid, name }` (DAM) or `{ templateId, content, name, templateQuery }` (stateless; under `dam-store` also `stored: { uuid, url }` or `storeError`) |
|
|
334
382
|
| `dirtychange` | `{ isDirty }` (stateless) |
|
|
335
|
-
| `close` | — (user left the editor, or it unmounted) |
|
|
383
|
+
| `close` | — (user left the editor, or it unmounted). A `dam-store` save whose upload is still in flight emits **after** `close` — keep listening |
|
|
336
384
|
| `error` | `{ code, message? }` |
|
|
337
385
|
|
|
338
386
|
`error` codes: `auth`, `invalid-content`, `invalid-config`,
|
|
339
387
|
`handshake-timeout`, `invalid-base-url`, `unknown`.
|
|
340
388
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
save in Filerobot and adds `stored: { uuid, url }` (or `storeError`) to the
|
|
345
|
-
`save` detail — `url` + `templateQuery` is a render URL, and `store-folder`
|
|
346
|
-
names where templates with no existing DAM file land.
|
|
389
|
+
`dam-store`, `stored-uuid` and `custom-metadata-label` need bundle/package
|
|
390
|
+
**0.4.0+** — an older pinned bundle silently ignores the attributes. Check
|
|
391
|
+
the CHANGELOG against what the host pins.
|
|
347
392
|
|
|
348
393
|
## Public Methods
|
|
349
394
|
|
|
350
|
-
`open(templateId?)`, `close()`,
|
|
351
|
-
`
|
|
352
|
-
`
|
|
395
|
+
`open(templateId?)`, `close()`,
|
|
396
|
+
`load({ content, templateId?, name?, templateQuery?, storedUuid? })`
|
|
397
|
+
(omitting `storedUuid` clears the seed — it belongs to the document),
|
|
398
|
+
`createNew({ templateId?, name? })`, `confirmSave(ok, message?)`, and
|
|
399
|
+
`flushPendingSaves(reason?)` (only for framework wrappers that detach
|
|
400
|
+
listeners without removing the element; the React wrapper calls it itself).
|
|
401
|
+
Read-only: `status`, `isDirty`.
|
|
353
402
|
|
|
354
403
|
In React these are reached through a forwarded ref — **required for
|
|
355
404
|
`mode="modal"`**, which renders nothing until `open()` is called:
|
|
@@ -393,11 +442,11 @@ ignored; and `layout` / `locale` / `force_format` are reserved slugs.
|
|
|
393
442
|
|
|
394
443
|
| Symptom | Cause |
|
|
395
444
|
|---|---|
|
|
396
|
-
| `error` code `handshake-timeout`, nothing rendered | Host origin not in the deployment's embedding allowlist (Step
|
|
445
|
+
| `error` code `handshake-timeout`, nothing rendered | Host origin not in the deployment's embedding allowlist (Step 9), or third-party cookies blocked |
|
|
397
446
|
| `error` code `auth` | Bad/expired session credentials, a rejected security template, or cookies blocked |
|
|
398
447
|
| `error` code `invalid-content` | The `content` handed over is not parseable `.fdt` XML |
|
|
399
|
-
| `error` code `invalid-config` | `sec-template` without `stateless` (Step
|
|
400
|
-
| Metadata / regional / branding panels empty | Expected under `sec-template` — those come from the Hub project (Step
|
|
448
|
+
| `error` code `invalid-config` | `sec-template` without `stateless` (Step 8) |
|
|
449
|
+
| Metadata / regional / branding panels empty | Expected under `sec-template` — those come from the Hub project (Step 8) |
|
|
401
450
|
| Nothing renders, no events | `inline` mode inside a zero-height parent — size the element |
|
|
402
451
|
| Modal never appears | `open()` never called; in React that needs a ref |
|
|
403
452
|
| Saves look successful but nothing is stored | `confirmSave(false)` not wired (Step 5) |
|
package/package.json
CHANGED