@persona/layout-editor-remote-module 0.6.0 → 0.8.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/README.md CHANGED
@@ -115,6 +115,11 @@ cannot derive itself:
115
115
  - `isReadOnly` — the host object is locked for edits
116
116
  - `isInEditor` — the module is rendered inside the layout editor rather than on a live record
117
117
  - `isUsingStubData` — the host is feeding placeholder/stub data instead of a real record
118
+ - `dynamicHeight` — whether the host sizes the iframe to the height the bridge reports
119
+ (`RemoteModuleFrame`'s `dynamicHeight`). A module that fills a fixed-height iframe with viewport
120
+ units (`100vh`) should size to its content when it's set, or the reported height just follows the
121
+ iframe. `RemoteModuleFrame` sets it from its `dynamicHeight` prop, overriding any value in the
122
+ `context` prop.
118
123
 
119
124
  `context` is sent with `init` and pushed again whenever it changes, just like `data`; inside the
120
125
  iframe it arrives through `ready()`, `getContext()`, and the `context` render prop (all
@@ -1,4 +1,4 @@
1
- import { n as Json, t as RemoteModuleContext } from "./protocol-BljV-Zhi.mjs";
1
+ import { n as Json, t as RemoteModuleContext } from "./protocol-Dqnl8JTs.mjs";
2
2
  import { ReactNode } from "react";
3
3
 
4
4
  //#region src/bridge/origin.d.ts
@@ -1,4 +1,4 @@
1
- import { c as resolveAllowedHostOrigins, n as SOURCE, o as candidateParentOrigin, r as parseHostToModuleMessage, s as personaDashboardHostOrigins, t as PROTOCOL_VERSION } from "./protocol-BQsn3N3N.mjs";
1
+ import { c as resolveAllowedHostOrigins, n as SOURCE, o as candidateParentOrigin, r as parseHostToModuleMessage, s as personaDashboardHostOrigins, t as PROTOCOL_VERSION } from "./protocol-D_pdVZjs.mjs";
2
2
  import { Component, useEffect, useRef, useState } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
@@ -1,4 +1,4 @@
1
- import { n as Json, t as RemoteModuleContext } from "./protocol-BljV-Zhi.mjs";
1
+ import { n as Json, t as RemoteModuleContext } from "./protocol-Dqnl8JTs.mjs";
2
2
  import { CSSProperties, ReactNode } from "react";
3
3
 
4
4
  //#region src/bridge/host/buildModuleSrc.d.ts
@@ -1,4 +1,4 @@
1
- import { a as assertNotSelfOrigin, i as parseModuleToHostMessage, n as SOURCE, t as PROTOCOL_VERSION } from "./protocol-BQsn3N3N.mjs";
1
+ import { a as assertNotSelfOrigin, i as parseModuleToHostMessage, n as SOURCE, t as PROTOCOL_VERSION } from "./protocol-D_pdVZjs.mjs";
2
2
  import { useEffect, useMemo, useRef, useState } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
@@ -139,16 +139,23 @@ function createHostBridge({ iframe, moduleOrigin, getData, getContext, resolveDa
139
139
 
140
140
  //#endregion
141
141
  //#region src/bridge/host/RemoteModuleFrame.tsx
142
+ function withDynamicHeight(context, dynamicHeight) {
143
+ return {
144
+ ...context,
145
+ dynamicHeight
146
+ };
147
+ }
142
148
  function RemoteModuleFrame({ documentUrl, moduleOrigin, accessToken, environmentId, locale, extraParams, title, sandbox, referrerPolicy = "no-referrer", initRetryMs, initRetryTimeoutMs, dynamicHeight = false, heightOffset = 0, minHeight, className, style, data, context, resolveDataPath, onRenderError }) {
143
149
  const iframeRef = useRef(null);
144
150
  const dataRef = useRef(data);
145
- const contextRef = useRef(context);
151
+ const contextRef = useRef(withDynamicHeight(context, dynamicHeight));
146
152
  const onRenderErrorRef = useRef(onRenderError);
147
153
  const resolveDataPathRef = useRef(resolveDataPath);
148
154
  const bridgeRef = useRef(void 0);
149
155
  const [height, setHeight] = useState();
156
+ const hostContext = useMemo(() => withDynamicHeight(context, dynamicHeight), [context, dynamicHeight]);
150
157
  dataRef.current = data;
151
- contextRef.current = context;
158
+ contextRef.current = hostContext;
152
159
  onRenderErrorRef.current = onRenderError;
153
160
  resolveDataPathRef.current = resolveDataPath;
154
161
  const src = useMemo(() => buildModuleSrc(documentUrl, {
@@ -194,8 +201,8 @@ function RemoteModuleFrame({ documentUrl, moduleOrigin, accessToken, environment
194
201
  bridgeRef.current?.pushData(data);
195
202
  }, [data]);
196
203
  useEffect(() => {
197
- bridgeRef.current?.pushContext(context);
198
- }, [context]);
204
+ bridgeRef.current?.pushContext(hostContext);
205
+ }, [hostContext]);
199
206
  const computedHeight = dynamicHeight && height !== void 0 ? `${Math.max(height + heightOffset, minHeight ?? 0)}px` : minHeight === void 0 ? "100%" : `${minHeight}px`;
200
207
  return /* @__PURE__ */ jsx("iframe", {
201
208
  ref: iframeRef,
@@ -39,6 +39,7 @@ declare const remoteModuleRegistrationManifestV1Schema: z.ZodObject<{
39
39
  management: "management";
40
40
  related_records: "related_records";
41
41
  }>>;
42
+ categoryCustom: z.ZodOptional<z.ZodString>;
42
43
  configSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
43
44
  defaultSize: z.ZodRecord<z.ZodEnum<{
44
45
  account: "account";
@@ -118,6 +119,8 @@ interface LayoutModuleDefinitionInput {
118
119
  allowDynamicHeight?: boolean;
119
120
  badge?: ModuleBadge;
120
121
  category?: ModuleCategory;
122
+ /** Free-form module-library category label; takes precedence over `category` when both are set. */
123
+ categoryCustom?: string;
121
124
  /** Authored as zod; converted to JSON Schema by the plugin. */
122
125
  configSchema?: z.ZodType;
123
126
  defaultSize: Partial<Record<LayoutType, {
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as JsonSchemaObject, c as ModuleCategory, d as RemoteModuleRegistrationManifestV1Schema, f as remoteModuleRegistrationManifestV1Schema, i as Json, l as RemoteModuleDelivery, n as LayoutModuleEntry, o as LayoutType, r as defineLayoutModule, s as ModuleBadge, t as LayoutModuleDefinitionInput, u as RemoteModuleRegistrationManifestV1 } from "./define-CUJkJjCk.mjs";
1
+ import { a as JsonSchemaObject, c as ModuleCategory, d as RemoteModuleRegistrationManifestV1Schema, f as remoteModuleRegistrationManifestV1Schema, i as Json, l as RemoteModuleDelivery, n as LayoutModuleEntry, o as LayoutType, r as defineLayoutModule, s as ModuleBadge, t as LayoutModuleDefinitionInput, u as RemoteModuleRegistrationManifestV1 } from "./define-Bxk_kfEr.mjs";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/manifest-path.d.ts
@@ -44,6 +44,7 @@ declare const remoteModuleManifestDocumentSchema: z.ZodObject<{
44
44
  management: "management";
45
45
  related_records: "related_records";
46
46
  }>>;
47
+ categoryCustom: z.ZodOptional<z.ZodString>;
47
48
  configSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
48
49
  defaultSize: z.ZodRecord<z.ZodEnum<{
49
50
  account: "account";
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as DEFAULT_MANIFEST_PATH, r as defineLayoutModule, t as remoteModuleRegistrationManifestV1Schema } from "./schema-DoUyVRjU.mjs";
1
+ import { n as DEFAULT_MANIFEST_PATH, r as defineLayoutModule, t as remoteModuleRegistrationManifestV1Schema } from "./schema-DU2LTDDC.mjs";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/parse.ts
@@ -80,6 +80,7 @@ const remoteModuleRegistrationManifestV1Schema = z.object({
80
80
  allowDynamicHeight: z.boolean().optional(),
81
81
  badge: moduleBadgeSchema.optional(),
82
82
  category: moduleCategorySchema.optional(),
83
+ categoryCustom: z.string().trim().min(1).max(80).optional(),
83
84
  configSchema: looseObjectSchema.optional(),
84
85
  defaultSize: z.partialRecord(layoutTypeSchema, gridSizeSchema),
85
86
  descriptionShort: z.string().min(1),
@@ -155,7 +156,8 @@ const remoteModuleContextSchema = z.object({
155
156
  layoutObjectId: z.string().nullable(),
156
157
  isReadOnly: z.boolean(),
157
158
  isInEditor: z.boolean(),
158
- isUsingStubData: z.boolean()
159
+ isUsingStubData: z.boolean(),
160
+ dynamicHeight: z.boolean().optional()
159
161
  });
160
162
  const moduleToHostMessageSchema = z.discriminatedUnion("type", [
161
163
  readySchema,
@@ -20,6 +20,7 @@ declare const remoteModuleContextSchema: z.ZodObject<{
20
20
  isReadOnly: z.ZodBoolean;
21
21
  isInEditor: z.ZodBoolean;
22
22
  isUsingStubData: z.ZodBoolean;
23
+ dynamicHeight: z.ZodOptional<z.ZodBoolean>;
23
24
  }, z.core.$strip>;
24
25
  type RemoteModuleContext = z.infer<typeof remoteModuleContextSchema>;
25
26
  //#endregion
@@ -78,6 +78,7 @@ const remoteModuleRegistrationManifestV1Schema = z.object({
78
78
  allowDynamicHeight: z.boolean().optional(),
79
79
  badge: moduleBadgeSchema.optional(),
80
80
  category: moduleCategorySchema.optional(),
81
+ categoryCustom: z.string().trim().min(1).max(80).optional(),
81
82
  configSchema: looseObjectSchema.optional(),
82
83
  defaultSize: z.partialRecord(layoutTypeSchema, gridSizeSchema),
83
84
  descriptionShort: z.string().min(1),
@@ -1,4 +1,4 @@
1
- import { n as LayoutModuleEntry, r as defineLayoutModule, t as LayoutModuleDefinitionInput } from "./define-CUJkJjCk.mjs";
1
+ import { n as LayoutModuleEntry, r as defineLayoutModule, t as LayoutModuleDefinitionInput } from "./define-Bxk_kfEr.mjs";
2
2
  import { Plugin } from "vite";
3
3
 
4
4
  //#region src/vite-plugin.d.ts
@@ -1,4 +1,4 @@
1
- import { n as DEFAULT_MANIFEST_PATH, r as defineLayoutModule, t as remoteModuleRegistrationManifestV1Schema } from "./schema-DoUyVRjU.mjs";
1
+ import { n as DEFAULT_MANIFEST_PATH, r as defineLayoutModule, t as remoteModuleRegistrationManifestV1Schema } from "./schema-DU2LTDDC.mjs";
2
2
  import { z } from "zod";
3
3
  import { existsSync } from "node:fs";
4
4
  import { mkdir, writeFile } from "node:fs/promises";
@@ -113,6 +113,7 @@ function buildManifestBase(definition) {
113
113
  allowDynamicHeight: input.allowDynamicHeight,
114
114
  badge: input.badge,
115
115
  category: input.category,
116
+ categoryCustom: input.categoryCustom,
116
117
  configSchema: input.configSchema ? z.toJSONSchema(input.configSchema) : void 0,
117
118
  defaultSize: input.defaultSize,
118
119
  descriptionShort: input.descriptionShort,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@persona/layout-editor-remote-module",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Shared manifest format, Vite plugin, and host/iframe bridge for remotely-defined dashboard layout modules in Persona dashboard apps.",
5
5
  "license": "SEE LICENSE",
6
6
  "type": "module",
@@ -68,7 +68,12 @@ specific layouts, `defaultSize` must provide an entry for each one.
68
68
  Optional fields: `allowDynamicHeight` (expose the dynamic-height option in the module's
69
69
  configuration), `badge` (`'beta' | 'deprecated' | 'improved' | 'new'`), `category`
70
70
  (`'build_your_own' | 'components' | 'management' | 'related_records'`; the host defaults to
71
- `build_your_own`), `icon` (an image path relative to the module's origin, such as
71
+ `build_your_own`), `categoryCustom` (a free-form module-library category label, up to 80 characters;
72
+ the host renders it verbatim — it is not translated — and groups modules that share the same
73
+ trimmed, case-sensitive string, even across different module sources. When both are set,
74
+ `categoryCustom` overrides `category`, and a label equal to one of the host's built-in category
75
+ labels lands in "Other"; keep setting `category` as a fallback for hosts that predate
76
+ `categoryCustom`), `icon` (an image path relative to the module's origin, such as
72
77
  `/assets/icon.svg`; the library shows a generic icon when it's omitted, fails to load, or is
73
78
  rejected as a cross-origin or non-http(s) URL), `internalUsersOnly` (a hint the host may use to
74
79
  narrow visibility, never widen it), and `configSchema` / `uiConfigSchema` (below).