[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/script-modules/widget-primitives/ -> index.js (source)

   1  var __create = Object.create;
   2  var __defProp = Object.defineProperty;
   3  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
   4  var __getOwnPropNames = Object.getOwnPropertyNames;
   5  var __getProtoOf = Object.getPrototypeOf;
   6  var __hasOwnProp = Object.prototype.hasOwnProperty;
   7  var __commonJS = (cb, mod) => function __require() {
   8    return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
   9  };
  10  var __copyProps = (to, from, except, desc) => {
  11    if (from && typeof from === "object" || typeof from === "function") {
  12      for (let key of __getOwnPropNames(from))
  13        if (!__hasOwnProp.call(to, key) && key !== except)
  14          __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15    }
  16    return to;
  17  };
  18  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  19    // If the importer is in node compatibility mode or this is not an ESM
  20    // file that has been converted to a CommonJS file using a Babel-
  21    // compatible transform (i.e. "__esModule" has not been set), then set
  22    // "default" to the CommonJS "module.exports" for node compatibility.
  23    isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  24    mod
  25  ));
  26  
  27  // package-external:@wordpress/element
  28  var require_element = __commonJS({
  29    "package-external:@wordpress/element"(exports, module) {
  30      module.exports = window.wp.element;
  31    }
  32  });
  33  
  34  // vendor-external:react/jsx-runtime
  35  var require_jsx_runtime = __commonJS({
  36    "vendor-external:react/jsx-runtime"(exports, module) {
  37      module.exports = window.ReactJSXRuntime;
  38    }
  39  });
  40  
  41  // packages/widget-primitives/build-module/tools/get-lazy-widget-component/get-lazy-widget-component.mjs
  42  var import_element = __toESM(require_element(), 1);
  43  function isValidWidgetModule(module) {
  44    return typeof module === "object" && module !== null && "default" in module && typeof module.default === "function";
  45  }
  46  var componentCache = /* @__PURE__ */ new Map();
  47  function getLazyWidgetComponent(renderModule, resolveWidgetModule) {
  48    const cached = componentCache.get(renderModule);
  49    if (cached) {
  50      return cached;
  51    }
  52    const lazyComponent = (0, import_element.lazy)(async () => {
  53      const module = await resolveWidgetModule(renderModule);
  54      if (!isValidWidgetModule(module)) {
  55        throw new Error(`Invalid widget module: $renderModule}`);
  56      }
  57      return module;
  58    });
  59    componentCache.set(renderModule, lazyComponent);
  60    return lazyComponent;
  61  }
  62  
  63  // packages/widget-primitives/build-module/widget-host/widget-actions-collector.mjs
  64  var import_element3 = __toESM(require_element(), 1);
  65  
  66  // packages/widget-primitives/build-module/widget-host/widget-host.mjs
  67  var import_element2 = __toESM(require_element(), 1);
  68  var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
  69  var WidgetHostContext = (0, import_element2.createContext)({});
  70  function WidgetHostProvider({
  71    value,
  72    children
  73  }) {
  74    const inherited = (0, import_element2.useContext)(WidgetHostContext);
  75    const merged = (0, import_element2.useMemo)(
  76      () => ({ ...inherited, ...value }),
  77      [inherited, value]
  78    );
  79    return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WidgetHostContext.Provider, { value: merged, children });
  80  }
  81  function useWidgetHost() {
  82    return (0, import_element2.useContext)(WidgetHostContext);
  83  }
  84  
  85  // packages/widget-primitives/build-module/widget-host/widget-actions-collector.mjs
  86  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
  87  var WidgetActionsCollectorContext = (0, import_element3.createContext)(null);
  88  function useWidgetActionsCollector() {
  89    return (0, import_element3.useContext)(WidgetActionsCollectorContext);
  90  }
  91  function joinDeclarations(declarations) {
  92    const byId = /* @__PURE__ */ new Map();
  93    for (const actions of declarations.values()) {
  94      for (const action of actions) {
  95        byId.set(action.id, action);
  96      }
  97    }
  98    return [...byId.values()];
  99  }
 100  function WidgetActionsCollector({
 101    children
 102  }) {
 103    const hostDeclare = useWidgetHost().actions?.declare;
 104    const [declarations] = (0, import_element3.useState)(
 105      () => /* @__PURE__ */ new Map()
 106    );
 107    const value = (0, import_element3.useMemo)(
 108      () => ({
 109        hosted: !!hostDeclare,
 110        declare: (callId, actions) => {
 111          if (actions.length > 0) {
 112            declarations.set(callId, actions);
 113          } else {
 114            declarations.delete(callId);
 115          }
 116          hostDeclare?.(joinDeclarations(declarations));
 117        }
 118      }),
 119      [hostDeclare, declarations]
 120    );
 121    return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(WidgetActionsCollectorContext.Provider, { value, children });
 122  }
 123  
 124  // packages/widget-primitives/build-module/components/widget-render/widget-render.mjs
 125  var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
 126  function WidgetRender({
 127    widgetType,
 128    attributes,
 129    setAttributes,
 130    resolveWidgetModule
 131  }) {
 132    const WidgetComponent = getLazyWidgetComponent(
 133      widgetType.renderModule,
 134      resolveWidgetModule
 135    );
 136    return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WidgetActionsCollector, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
 137      WidgetComponent,
 138      {
 139        attributes,
 140        setAttributes
 141      }
 142    ) });
 143  }
 144  
 145  // packages/widget-primitives/build-module/hooks/use-widget-actions.mjs
 146  var import_element5 = __toESM(require_element(), 1);
 147  
 148  // packages/widget-primitives/build-module/widget-host/host-link.mjs
 149  var import_element4 = __toESM(require_element(), 1);
 150  var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
 151  var HostLink = (0, import_element4.forwardRef)(
 152    function UnforwardedHostLink({ href, children, ...props }, ref) {
 153      const { links } = useWidgetHost();
 154      const { download, target } = props;
 155      const opensNewDocument = download !== void 0 && download !== false || /^_blank$/i.test(target ?? "");
 156      const path = links && !opensNewDocument ? links.match(href) : null;
 157      if (links && path !== null) {
 158        return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(links.Link, { ref, path, ...props, children });
 159      }
 160      return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { ref, href, ...props, children });
 161    }
 162  );
 163  
 164  // packages/widget-primitives/build-module/hooks/use-widget-actions.mjs
 165  var NO_ACTIONS = [];
 166  function isSameAction(a, b) {
 167    const left = a;
 168    const right = b;
 169    const keys = Object.keys(left);
 170    return keys.length === Object.keys(right).length && keys.every(
 171      (key) => Object.is(left[key], right[key]) || typeof left[key] === "function" && typeof right[key] === "function"
 172    );
 173  }
 174  function isSameList(a, b) {
 175    return a.length === b.length && a.every((action, index) => isSameAction(action, b[index]));
 176  }
 177  function useWidgetActions(actions) {
 178    const hostDeclare = useWidgetHost().actions?.declare;
 179    const collector = useWidgetActionsCollector();
 180    const callId = (0, import_element5.useId)();
 181    const declare = (0, import_element5.useMemo)(
 182      () => collector ? (next) => collector.declare(callId, next) : hostDeclare,
 183      [collector, hostDeclare, callId]
 184    );
 185    const latestRef = (0, import_element5.useRef)(actions);
 186    const declaredRef = (0, import_element5.useRef)(null);
 187    (0, import_element5.useLayoutEffect)(() => {
 188      latestRef.current = actions;
 189      if (!declare || declaredRef.current && isSameList(declaredRef.current, actions)) {
 190        return;
 191      }
 192      declaredRef.current = actions;
 193      declare(
 194        actions.map((action) => {
 195          if (!("callback" in action)) {
 196            return action;
 197          }
 198          return {
 199            ...action,
 200            callback: () => {
 201              const current = latestRef.current.find(
 202                ({ id }) => id === action.id
 203              );
 204              return current && "callback" in current ? current.callback() : void 0;
 205            }
 206          };
 207        })
 208      );
 209    });
 210    (0, import_element5.useLayoutEffect)(
 211      () => () => {
 212        declaredRef.current = null;
 213        declare?.(NO_ACTIONS);
 214      },
 215      [declare]
 216    );
 217    return collector ? collector.hosted : !!hostDeclare;
 218  }
 219  
 220  // packages/widget-primitives/build-module/hooks/use-widget-types.mjs
 221  var import_element6 = __toESM(require_element(), 1);
 222  
 223  // packages/widget-primitives/build-module/field-types/field-types.mjs
 224  var FIELD_TYPE_NAME_PATTERN = /^[a-z][a-z0-9-]*(\/[a-z][a-z0-9-]*)?$/;
 225  var fieldTypes = /* @__PURE__ */ new Map();
 226  function registerFieldType(fieldType) {
 227    if (!FIELD_TYPE_NAME_PATTERN.test(fieldType.name) || fieldTypes.has(fieldType.name)) {
 228      return void 0;
 229    }
 230    fieldTypes.set(fieldType.name, fieldType);
 231    return fieldType;
 232  }
 233  function resolveFields(fields) {
 234    return fields.map((field) => {
 235      const fieldType = field.type ? fieldTypes.get(field.type) : void 0;
 236      if (!fieldType) {
 237        return field;
 238      }
 239      const { name, baseType, isValid, ...fieldDefaults } = fieldType;
 240      const { type, isValid: fieldIsValid, ...rest } = field;
 241      return {
 242        ...fieldDefaults,
 243        ...rest,
 244        type: baseType,
 245        ...isValid || fieldIsValid ? { isValid: { ...isValid, ...fieldIsValid } } : {}
 246      };
 247    });
 248  }
 249  
 250  // packages/widget-primitives/build-module/icon-resolver/icon-resolver.mjs
 251  var iconResolver;
 252  function registerIconResolver(resolver) {
 253    if (iconResolver) {
 254      return void 0;
 255    }
 256    iconResolver = resolver;
 257    return resolver;
 258  }
 259  async function resolveIcon(reference) {
 260    if (!iconResolver) {
 261      return null;
 262    }
 263    try {
 264      return await iconResolver(reference);
 265    } catch {
 266      return null;
 267    }
 268  }
 269  
 270  // packages/widget-primitives/build-module/hooks/use-widget-types.mjs
 271  var pendingIcon = (0, import_element6.createElement)("svg", {
 272    viewBox: "0 0 24 24"
 273  });
 274  function withRenderableIcons(actions, holdPending) {
 275    return actions.map(({ icon, ...action }) => {
 276      if ((0, import_element6.isValidElement)(icon)) {
 277        return { ...action, icon };
 278      }
 279      if (holdPending && typeof icon === "string") {
 280        return { ...action, icon: pendingIcon };
 281      }
 282      return action;
 283    });
 284  }
 285  function mergeAttributes(recordAttributes, moduleAttributes) {
 286    if (!recordAttributes) {
 287      return moduleAttributes;
 288    }
 289    if (!moduleAttributes) {
 290      return recordAttributes;
 291    }
 292    const moduleById = new Map(
 293      moduleAttributes.map(
 294        (attribute) => [attribute.id, attribute]
 295      )
 296    );
 297    const recordIds = new Set(
 298      recordAttributes.map((attribute) => attribute.id)
 299    );
 300    return [
 301      ...recordAttributes.map((attribute) => {
 302        const moduleAttribute = moduleById.get(attribute.id);
 303        if (!moduleAttribute?.isValid || !attribute.isValid) {
 304          return { ...moduleAttribute, ...attribute };
 305        }
 306        return {
 307          ...moduleAttribute,
 308          ...attribute,
 309          isValid: { ...moduleAttribute.isValid, ...attribute.isValid }
 310        };
 311      }),
 312      ...moduleAttributes.filter(
 313        (attribute) => !recordIds.has(attribute.id)
 314      )
 315    ];
 316  }
 317  var DEFAULT_API_VERSION = 1;
 318  function recordOverlay(record) {
 319    return {
 320      name: record.name,
 321      renderModule: record.render_module ?? "",
 322      ...record.presentation ? { presentation: record.presentation } : {},
 323      ...record.category ? { category: record.category } : {},
 324      ...record.description ? { description: record.description } : {},
 325      ...record.help ? { help: record.help } : {},
 326      ...record.keywords ? { keywords: record.keywords } : {}
 327    };
 328  }
 329  function useWidgetTypes(records) {
 330    const [widgetTypes, setWidgetTypes] = (0, import_element6.useState)([]);
 331    const [isResolvingWidgetTypes, setIsResolvingWidgetTypes] = (0, import_element6.useState)(true);
 332    (0, import_element6.useEffect)(() => {
 333      if (records === null || records === void 0) {
 334        setIsResolvingWidgetTypes(true);
 335        return;
 336      }
 337      if (records.length === 0) {
 338        setWidgetTypes([]);
 339        setIsResolvingWidgetTypes(false);
 340        return;
 341      }
 342      let cancelled = false;
 343      setIsResolvingWidgetTypes(true);
 344      Promise.all(
 345        records.map(async (record) => {
 346          if (!record.widget_module) {
 347            if (!record.render_module) {
 348              return null;
 349            }
 350            return {
 351              apiVersion: DEFAULT_API_VERSION,
 352              title: record.title ?? record.name,
 353              ...record.attributes ? {
 354                attributes: resolveFields(
 355                  record.attributes
 356                )
 357              } : {},
 358              ...record.icon ? { icon: pendingIcon } : {},
 359              ...record.actions ? {
 360                actions: withRenderableIcons(
 361                  record.actions,
 362                  true
 363                )
 364              } : {},
 365              ...recordOverlay(record)
 366            };
 367          }
 368          try {
 369            const module = await import(
 370              /* webpackIgnore: true */
 371              /* @vite-ignore */
 372              record.widget_module
 373            );
 374            if (!module?.default) {
 375              return null;
 376            }
 377            const metadata = module.default;
 378            const moduleIcon = (0, import_element6.isValidElement)(metadata.icon) ? metadata.icon : void 0;
 379            const icon = moduleIcon ?? (record.icon ? pendingIcon : void 0);
 380            const actions = record.actions ?? metadata.actions;
 381            const attributes = mergeAttributes(
 382              record.attributes,
 383              metadata.attributes
 384            );
 385            return {
 386              apiVersion: DEFAULT_API_VERSION,
 387              ...metadata,
 388              ...attributes ? { attributes: resolveFields(attributes) } : {},
 389              icon,
 390              /*
 391               * `title` is required:
 392               * - Server-side title wins
 393               * - Then the module's title
 394               * - Then the record's name as fallback
 395               */
 396              title: record.title ?? metadata.title ?? record.name,
 397              ...actions ? {
 398                actions: withRenderableIcons(
 399                  actions,
 400                  actions === record.actions
 401                )
 402              } : {},
 403              ...recordOverlay(record)
 404            };
 405          } catch {
 406            return null;
 407          }
 408        })
 409      ).then((results) => {
 410        if (cancelled) {
 411          return;
 412        }
 413        setWidgetTypes(
 414          results.filter((t) => t !== null)
 415        );
 416        setIsResolvingWidgetTypes(false);
 417        for (const record of records) {
 418          if (!record.icon) {
 419            continue;
 420          }
 421          void resolveIcon(record.icon).then((resolved) => {
 422            if (cancelled) {
 423              return;
 424            }
 425            setWidgetTypes(
 426              (prev) => prev.map((widgetType) => {
 427                if (widgetType.name !== record.name) {
 428                  return widgetType;
 429                }
 430                if (resolved) {
 431                  return { ...widgetType, icon: resolved };
 432                }
 433                return widgetType.icon === pendingIcon ? { ...widgetType, icon: void 0 } : widgetType;
 434              })
 435            );
 436          });
 437        }
 438        for (const record of records) {
 439          for (const action of record.actions ?? []) {
 440            if (typeof action.icon !== "string") {
 441              continue;
 442            }
 443            void resolveIcon(action.icon).then((resolved) => {
 444              if (cancelled) {
 445                return;
 446              }
 447              setWidgetTypes(
 448                (prev) => prev.map((type) => {
 449                  if (type.name !== record.name) {
 450                    return type;
 451                  }
 452                  return {
 453                    ...type,
 454                    actions: type.actions?.map((entry) => {
 455                      if (entry.id !== action.id) {
 456                        return entry;
 457                      }
 458                      if (resolved) {
 459                        return {
 460                          ...entry,
 461                          icon: resolved
 462                        };
 463                      }
 464                      return entry.icon === pendingIcon ? { ...entry, icon: void 0 } : entry;
 465                    })
 466                  };
 467                })
 468              );
 469            });
 470          }
 471        }
 472      });
 473      return () => {
 474        cancelled = true;
 475      };
 476    }, [records]);
 477    return [widgetTypes, isResolvingWidgetTypes];
 478  }
 479  export {
 480    HostLink,
 481    WidgetHostProvider,
 482    WidgetRender,
 483    registerFieldType,
 484    registerIconResolver,
 485    useWidgetActions,
 486    useWidgetHost,
 487    useWidgetTypes
 488  };


Generated : Mon Nov 9 08:20:01 2026 Cross-referenced by PHPXref