@avocadostudio-ai/site-sdk 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/editor.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { FieldKind } from "@avocadostudio-ai/shared";
1
2
  export { EditorOverlay } from "./editor-overlay.tsx";
2
3
  export { buildEditorQuerySuffix } from "./editor-query.ts";
3
4
  export declare function getPreviewWrapperProps(editorMode: boolean, blockId: string, blockType: string): {
@@ -13,6 +14,57 @@ export declare function getPreviewWrapperProps(editorMode: boolean, blockId: str
13
14
  readonly viewTransitionName: `block-${string}`;
14
15
  };
15
16
  };
17
+ /**
18
+ * Mark the element that draws one editable field.
19
+ *
20
+ * This is the second half of instrumenting a preview, and until now it was the
21
+ * half with no helper. `getPreviewWrapperProps` covers the block boundary and
22
+ * is named, exported and documented; the per-field attributes were prose in the
23
+ * integration guide with a link to a renderer to copy from. The predictable
24
+ * result is an integration that wraps every block and marks no fields — which
25
+ * frames, renders, selects, scrolls and opens the property panel correctly, and
26
+ * silently has no inline text editing, no field pills and no image buttons in
27
+ * the preview, because every one of those is found by walking
28
+ * `[data-editable-target]`.
29
+ *
30
+ * ```tsx
31
+ * <div className="hero__media" {...editableProps("imageUrl", { kind: "image" })}>
32
+ * <Image src={props.imageUrl} … />
33
+ * </div>
34
+ * ```
35
+ *
36
+ * The path is the same grammar an operation uses — `title`, `cards[0].title`,
37
+ * `links[0].children[1].label` — because it is the same path: what the overlay
38
+ * reads here is what it sends back as the field to patch.
39
+ *
40
+ * **Put it on an element, not on the image.** For an image field the attribute
41
+ * belongs on the wrapper around the `<img>`, never on the image itself: the
42
+ * overlay appends its Change button *into* the marked element, and nothing can
43
+ * be appended into an `<img>`.
44
+ *
45
+ * **`kind` is how a site says what a field is in its own vocabulary.** Without
46
+ * it the overlay has to guess an image from the prop name, against Avocado's
47
+ * own naming (`imageUrl`, `*.src`) — so a site whose field is `photoUrl` or
48
+ * `heroSrc` gets a picker in the property panel and no button in the preview,
49
+ * with no error on either side. Pass the same word the block manifest uses and
50
+ * the guess never runs.
51
+ *
52
+ * There is no `editorMode` argument on purpose. These are inert data attributes
53
+ * that cost a few bytes and do nothing unless the overlay is mounted (all of
54
+ * its styling is scoped under `[data-editor-active]`), and most sites render
55
+ * their blocks through components shared with the public pages, where threading
56
+ * a flag down to every field is the step that does not get done.
57
+ */
58
+ export declare function editableProps(path: string, options?: {
59
+ /** Text for the hover pill. Defaults to the path. */
60
+ label?: string;
61
+ /** What kind of field this is — the same vocabulary as the block manifest. */
62
+ kind?: FieldKind;
63
+ }): {
64
+ readonly "data-editable-kind"?: FieldKind | undefined;
65
+ readonly "data-editable-target": string;
66
+ readonly "data-editable-target-label": string;
67
+ };
16
68
  export { renderBlocks } from "./render-blocks.tsx";
17
69
  export { RenderedBlocks, PreviewBlock } from "./live-preview-blocks.tsx";
18
70
  export { LivePreviewProvider } from "@avocadostudio-ai/preview-adapter";
package/dist/editor.js CHANGED
@@ -13,6 +13,54 @@ export function getPreviewWrapperProps(editorMode, blockId, blockType) {
13
13
  style: { viewTransitionName: `block-${blockId}` }
14
14
  };
15
15
  }
16
+ /**
17
+ * Mark the element that draws one editable field.
18
+ *
19
+ * This is the second half of instrumenting a preview, and until now it was the
20
+ * half with no helper. `getPreviewWrapperProps` covers the block boundary and
21
+ * is named, exported and documented; the per-field attributes were prose in the
22
+ * integration guide with a link to a renderer to copy from. The predictable
23
+ * result is an integration that wraps every block and marks no fields — which
24
+ * frames, renders, selects, scrolls and opens the property panel correctly, and
25
+ * silently has no inline text editing, no field pills and no image buttons in
26
+ * the preview, because every one of those is found by walking
27
+ * `[data-editable-target]`.
28
+ *
29
+ * ```tsx
30
+ * <div className="hero__media" {...editableProps("imageUrl", { kind: "image" })}>
31
+ * <Image src={props.imageUrl} … />
32
+ * </div>
33
+ * ```
34
+ *
35
+ * The path is the same grammar an operation uses — `title`, `cards[0].title`,
36
+ * `links[0].children[1].label` — because it is the same path: what the overlay
37
+ * reads here is what it sends back as the field to patch.
38
+ *
39
+ * **Put it on an element, not on the image.** For an image field the attribute
40
+ * belongs on the wrapper around the `<img>`, never on the image itself: the
41
+ * overlay appends its Change button *into* the marked element, and nothing can
42
+ * be appended into an `<img>`.
43
+ *
44
+ * **`kind` is how a site says what a field is in its own vocabulary.** Without
45
+ * it the overlay has to guess an image from the prop name, against Avocado's
46
+ * own naming (`imageUrl`, `*.src`) — so a site whose field is `photoUrl` or
47
+ * `heroSrc` gets a picker in the property panel and no button in the preview,
48
+ * with no error on either side. Pass the same word the block manifest uses and
49
+ * the guess never runs.
50
+ *
51
+ * There is no `editorMode` argument on purpose. These are inert data attributes
52
+ * that cost a few bytes and do nothing unless the overlay is mounted (all of
53
+ * its styling is scoped under `[data-editor-active]`), and most sites render
54
+ * their blocks through components shared with the public pages, where threading
55
+ * a flag down to every field is the step that does not get done.
56
+ */
57
+ export function editableProps(path, options) {
58
+ return {
59
+ "data-editable-target": path,
60
+ "data-editable-target-label": options?.label ?? path,
61
+ ...(options?.kind ? { "data-editable-kind": options.kind } : {})
62
+ };
63
+ }
16
64
  // Block rendering helper
17
65
  export { renderBlocks } from "./render-blocks.js";
18
66
  // Live-preview store renderer (streams field drafts through React)
@@ -1 +1 @@
1
- export { createOrchestrator, jsonFileAdapter, editorApiAdapter, resolveCapabilities, cmsMediaSource, cmsMediaLabel, type CreateOrchestratorConfig, type OrchestratorHandler, type OrchestratorAuth, type AuthContext, type CmsAdapter, type CmsCapabilities, type CmsInlineAsset, type CmsPublishContext, type CmsPublishResult, type CmsPerspective, type CmsReadOptions, type CmsMediaItem, type CmsMediaPage, type CmsMediaQuery, type CmsMediaSource, type CmsMediaSourceConfig, type ResolvedCapabilities } from "@avocadostudio-ai/orchestrator-core";
1
+ export { createOrchestrator, jsonFileAdapter, editorApiAdapter, resolveCapabilities, cmsMediaSource, cmsMediaUploader, cmsMediaLabel, type CreateOrchestratorConfig, type OrchestratorHandler, type OrchestratorAuth, type AuthContext, type CmsAdapter, type CmsCapabilities, type CmsInlineAsset, type CmsPublishContext, type CmsPublishResult, type CmsPerspective, type CmsReadOptions, type CmsMediaItem, type CmsMediaPage, type CmsMediaQuery, type CmsMediaUpload, type CmsMediaSource, type CmsMediaUploader, type CmsMediaSourceConfig, type ResolvedCapabilities } from "@avocadostudio-ai/orchestrator-core";
@@ -11,4 +11,4 @@
11
11
  //
12
12
  // This file stays so `@avocadostudio-ai/site-sdk/server` — the entry point
13
13
  // every example, README and docs page uses — keeps resolving unchanged.
14
- export { createOrchestrator, jsonFileAdapter, editorApiAdapter, resolveCapabilities, cmsMediaSource, cmsMediaLabel } from "@avocadostudio-ai/orchestrator-core";
14
+ export { createOrchestrator, jsonFileAdapter, editorApiAdapter, resolveCapabilities, cmsMediaSource, cmsMediaUploader, cmsMediaLabel } from "@avocadostudio-ai/orchestrator-core";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avocadostudio-ai/site-sdk",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -107,16 +107,16 @@
107
107
  ],
108
108
  "dependencies": {
109
109
  "zod": "^4.3.6",
110
- "@avocadostudio-ai/blocks": "^0.3.3",
111
- "@avocadostudio-ai/preview-adapter": "^0.3.3",
112
- "@avocadostudio-ai/shared": "^0.3.3"
110
+ "@avocadostudio-ai/blocks": "^0.4.0",
111
+ "@avocadostudio-ai/preview-adapter": "^0.4.0",
112
+ "@avocadostudio-ai/shared": "^0.4.0"
113
113
  },
114
114
  "peerDependencies": {
115
115
  "next": ">=15.0.0",
116
116
  "react": ">=19.0.0",
117
117
  "react-dom": ">=19.0.0",
118
118
  "better-sqlite3": ">=12.0.0",
119
- "@avocadostudio-ai/orchestrator-core": "^0.3.3"
119
+ "@avocadostudio-ai/orchestrator-core": "^0.4.0"
120
120
  },
121
121
  "peerDependenciesMeta": {
122
122
  "@avocadostudio-ai/orchestrator-core": {