@bettercms-ai/types 1.24.0 → 1.25.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/index.js CHANGED
@@ -2156,6 +2156,451 @@ var PAGE_CONTENT_ANCHOR_ID = "page-content";
2156
2156
  var NAVIGATION_SECTION_ID = "navigation";
2157
2157
  var FOOTER_SECTION_ID = "footer";
2158
2158
 
2159
+ // src/dock-icon-names.ts
2160
+ var DOCK_ICON_NAMES = [
2161
+ "access-denied",
2162
+ "activity",
2163
+ "add",
2164
+ "add-circle",
2165
+ "add-comment",
2166
+ "add-document",
2167
+ "add-user",
2168
+ "api",
2169
+ "archive",
2170
+ "arrow-down",
2171
+ "arrow-left",
2172
+ "arrow-right",
2173
+ "arrow-top-right",
2174
+ "arrow-up",
2175
+ "asterisk",
2176
+ "bar-chart",
2177
+ "basket",
2178
+ "bell",
2179
+ "bill",
2180
+ "binary-document",
2181
+ "block-content",
2182
+ "block-element",
2183
+ "blockquote",
2184
+ "bold",
2185
+ "bolt",
2186
+ "book",
2187
+ "bookmark",
2188
+ "bookmark-filled",
2189
+ "bottle",
2190
+ "bug",
2191
+ "bulb-filled",
2192
+ "bulb-outline",
2193
+ "calendar",
2194
+ "case",
2195
+ "chart-upward",
2196
+ "checkmark",
2197
+ "checkmark-circle",
2198
+ "chevron-down",
2199
+ "chevron-left",
2200
+ "chevron-right",
2201
+ "chevron-up",
2202
+ "circle",
2203
+ "clipboard",
2204
+ "clipboard-image",
2205
+ "clock",
2206
+ "close",
2207
+ "close-circle",
2208
+ "code",
2209
+ "code-block",
2210
+ "cog",
2211
+ "collapse",
2212
+ "color-wheel",
2213
+ "comment",
2214
+ "component",
2215
+ "compose",
2216
+ "compose-sparkles",
2217
+ "confetti",
2218
+ "controls",
2219
+ "copy",
2220
+ "credit-card",
2221
+ "crop",
2222
+ "cube",
2223
+ "dashboard",
2224
+ "database",
2225
+ "desktop",
2226
+ "diamond",
2227
+ "document",
2228
+ "document-pdf",
2229
+ "document-remove",
2230
+ "document-sheet",
2231
+ "document-text",
2232
+ "document-video",
2233
+ "document-word",
2234
+ "document-zip",
2235
+ "documents",
2236
+ "dot",
2237
+ "double-chevron-down",
2238
+ "double-chevron-left",
2239
+ "double-chevron-right",
2240
+ "double-chevron-up",
2241
+ "double-quote",
2242
+ "download",
2243
+ "drag-handle",
2244
+ "drop",
2245
+ "earth-americas",
2246
+ "earth-globe",
2247
+ "edit",
2248
+ "ellipsis-horizontal",
2249
+ "ellipsis-vertical",
2250
+ "empty",
2251
+ "enter",
2252
+ "enter-right",
2253
+ "envelope",
2254
+ "equal",
2255
+ "error-filled",
2256
+ "error-outline",
2257
+ "error-screen",
2258
+ "expand",
2259
+ "eye-closed",
2260
+ "eye-open",
2261
+ "face-happy",
2262
+ "face-indifferent",
2263
+ "face-sad",
2264
+ "feedback",
2265
+ "filter",
2266
+ "folder",
2267
+ "generate",
2268
+ "github",
2269
+ "groq",
2270
+ "hash",
2271
+ "heart",
2272
+ "heart-filled",
2273
+ "help-circle",
2274
+ "highlight",
2275
+ "home",
2276
+ "ice-cream",
2277
+ "image",
2278
+ "image-remove",
2279
+ "images",
2280
+ "inbox",
2281
+ "info-filled",
2282
+ "info-outline",
2283
+ "inline",
2284
+ "inline-element",
2285
+ "insert-above",
2286
+ "insert-below",
2287
+ "italic",
2288
+ "joystick",
2289
+ "json",
2290
+ "launch",
2291
+ "leave",
2292
+ "lemon",
2293
+ "link",
2294
+ "link-removed",
2295
+ "linkedin",
2296
+ "list",
2297
+ "lock",
2298
+ "logo-js",
2299
+ "logo-ts",
2300
+ "marker",
2301
+ "marker-removed",
2302
+ "master-detail",
2303
+ "menu",
2304
+ "microphone",
2305
+ "microphone-slash",
2306
+ "mobile-device",
2307
+ "moon",
2308
+ "number",
2309
+ "ok-hand",
2310
+ "olist",
2311
+ "overage",
2312
+ "package",
2313
+ "panel-left",
2314
+ "panel-right",
2315
+ "pause",
2316
+ "pin",
2317
+ "pin-filled",
2318
+ "pin-removed",
2319
+ "play",
2320
+ "plug",
2321
+ "presentation",
2322
+ "progress-50",
2323
+ "progress-75",
2324
+ "projects",
2325
+ "publish",
2326
+ "read-only",
2327
+ "redo",
2328
+ "refresh",
2329
+ "remove",
2330
+ "remove-circle",
2331
+ "reset",
2332
+ "restore",
2333
+ "retrieve",
2334
+ "retry",
2335
+ "revert",
2336
+ "robot",
2337
+ "rocket",
2338
+ "schema",
2339
+ "search",
2340
+ "select",
2341
+ "share",
2342
+ "sort",
2343
+ "sparkle",
2344
+ "sparkles",
2345
+ "spinner",
2346
+ "split-horizontal",
2347
+ "split-vertical",
2348
+ "square",
2349
+ "stack",
2350
+ "stack-compact",
2351
+ "star",
2352
+ "star-filled",
2353
+ "stop",
2354
+ "strikethrough",
2355
+ "string",
2356
+ "sun",
2357
+ "sync",
2358
+ "tablet-device",
2359
+ "tag",
2360
+ "tags",
2361
+ "target",
2362
+ "task",
2363
+ "terminal",
2364
+ "text",
2365
+ "th-large",
2366
+ "th-list",
2367
+ "thumbs-down",
2368
+ "thumbs-up",
2369
+ "tiers",
2370
+ "timeline",
2371
+ "toggle-arrow-right",
2372
+ "token",
2373
+ "transfer",
2374
+ "translate",
2375
+ "trash",
2376
+ "trend-upward",
2377
+ "triangle-outline",
2378
+ "trolley",
2379
+ "truncate",
2380
+ "twitter",
2381
+ "ulist",
2382
+ "unarchive",
2383
+ "underline",
2384
+ "undo",
2385
+ "unknown",
2386
+ "unlink",
2387
+ "unlock",
2388
+ "unpublish",
2389
+ "upload",
2390
+ "user",
2391
+ "users",
2392
+ "versions",
2393
+ "video",
2394
+ "warning-filled",
2395
+ "warning-outline",
2396
+ "wrench"
2397
+ ];
2398
+ var DOCK_ICON_NAME_SET = new Set(DOCK_ICON_NAMES);
2399
+
2400
+ // src/dock-budget.ts
2401
+ var DOCK_BUDGET = { ungrouped: 8, group: 12, depth: 3, activations: 2 };
2402
+ function listItems(f) {
2403
+ const c = f.config ?? {};
2404
+ if (f.type === "repeater") return f.fields ?? [];
2405
+ if (f.type === "table") return c.fields ?? f.fields ?? [];
2406
+ if (f.type === "array" && c.zones?.repeatable) return c.zones.repeatable.fields ?? [];
2407
+ if (f.type === "modular") return null;
2408
+ return void 0;
2409
+ }
2410
+ function zoneFields(f) {
2411
+ const c = f.config ?? {};
2412
+ if (f.type === "group") return c.fields ?? f.fields ?? [];
2413
+ if (f.type === "array" && c.zones?.nonRepeatable) return c.zones.nonRepeatable;
2414
+ return void 0;
2415
+ }
2416
+ function layout(fields, fieldsets, root) {
2417
+ const byId = new Map(fieldsets.map((s) => [s.id, s]));
2418
+ const tabIds = root ? fieldsets.filter((s) => s.kind === "tab").map((s) => s.id) : [];
2419
+ const tabOf = (s) => s?.kind === "tab" ? s.id : s?.tab !== void 0 && byId.get(s.tab)?.kind === "tab" ? s.tab : void 0;
2420
+ const nonEmpty = new Set(
2421
+ fields.map((f) => tabOf(byId.get(f.fieldsetId ?? ""))).filter((t) => t && tabIds.includes(t))
2422
+ );
2423
+ const strip = nonEmpty.size >= 2;
2424
+ const branches = /* @__PURE__ */ new Map();
2425
+ const nodeFor = (f, path) => {
2426
+ const key = `${path}${f.key}`;
2427
+ const zone = zoneFields(f);
2428
+ if (zone) {
2429
+ return { kind: "group", id: key, collapsed: f.ui?.collapsed === true, nodes: zone.map((z) => nodeFor(z, `${key}.`)) };
2430
+ }
2431
+ const items = listItems(f);
2432
+ if (items !== void 0) {
2433
+ branches.set(key, { key, field: f, items });
2434
+ return { kind: "branch", key };
2435
+ }
2436
+ return { kind: "leaf", key };
2437
+ };
2438
+ const pinned = [];
2439
+ const panels = new Map(strip ? tabIds.filter((t) => nonEmpty.has(t)).map((t) => [t, []]) : []);
2440
+ const containers = /* @__PURE__ */ new Map();
2441
+ for (const f of fields) {
2442
+ const node = nodeFor(f, "");
2443
+ const set = byId.get(f.fieldsetId ?? "");
2444
+ const target = strip && panels.get(tabOf(set) ?? "") || pinned;
2445
+ if (set?.kind !== "group" && set?.kind !== "row") {
2446
+ target.push(node);
2447
+ continue;
2448
+ }
2449
+ let box = containers.get(set.id);
2450
+ if (!box) {
2451
+ box = set.kind === "row" ? { kind: "row", id: set.id, keys: [] } : { kind: "group", id: set.id, collapsed: set.collapsed === true, nodes: [] };
2452
+ containers.set(set.id, box);
2453
+ target.push(box);
2454
+ }
2455
+ if (box.kind === "row") box.keys.push(f.key);
2456
+ else if (box.kind === "group") box.nodes.push(node);
2457
+ }
2458
+ return { pinned, tabs: [...panels.values()], branches };
2459
+ }
2460
+ function walkCosts(screen) {
2461
+ const values = [];
2462
+ const branchCost = /* @__PURE__ */ new Map();
2463
+ const walk = (nodes, cost) => {
2464
+ for (const n of nodes) {
2465
+ if (n.kind === "group") walk(n.nodes, cost + (n.collapsed ? 1 : 0));
2466
+ else if (n.kind === "branch") branchCost.set(n.key, cost);
2467
+ else values.push(cost);
2468
+ }
2469
+ };
2470
+ walk(screen.pinned, 0);
2471
+ screen.tabs.forEach((panel, i) => walk(panel, i === 0 ? 0 : 1));
2472
+ return { values, branchCost };
2473
+ }
2474
+ function dockScreens(source, lane, props) {
2475
+ let fields = source.fields ?? [];
2476
+ let fieldsets = source.fieldsets ?? [];
2477
+ if (props) {
2478
+ fieldsets = [];
2479
+ fields = props.map((p) => {
2480
+ const g = p.ui?.group;
2481
+ if (!g) return p;
2482
+ if (!fieldsets.some((s) => s.id === g.id)) {
2483
+ fieldsets.push({ id: g.id, name: g.label, kind: g.kind ?? "group", collapsed: g.collapsed });
2484
+ }
2485
+ return { ...p, fieldsetId: g.id };
2486
+ });
2487
+ }
2488
+ const screens = [];
2489
+ const open = (id, kind, title, depth, entry, level) => {
2490
+ const laid = level ? layout(level, fieldsets, kind === "root") : null;
2491
+ const screen = {
2492
+ id,
2493
+ lane,
2494
+ kind,
2495
+ title,
2496
+ depth,
2497
+ entry,
2498
+ pinned: laid?.pinned ?? [],
2499
+ tabs: laid?.tabs ?? []
2500
+ };
2501
+ screens.push(screen);
2502
+ if (!laid) return;
2503
+ const { branchCost } = walkCosts(screen);
2504
+ for (const b of laid.branches.values()) {
2505
+ const listId = `${id}/${b.key}`;
2506
+ const listEntry = entry + (branchCost.get(b.key) ?? 0) + 1;
2507
+ const label = b.field.label ?? b.field.key;
2508
+ open(listId, "list", label, depth + 1, listEntry, null);
2509
+ if (b.items) open(`${listId}/item`, "item", `${label} item`, depth + 2, listEntry + 1, b.items);
2510
+ }
2511
+ };
2512
+ open(lane, "root", lane === "component" ? "Component" : lane === "page-fields" ? "Page fields" : "Section", 0, 0, fields);
2513
+ return screens;
2514
+ }
2515
+ function dockBudget(screen) {
2516
+ const rows = (nodes) => nodes.filter((n) => n.kind !== "group").length;
2517
+ let maxGroupLeaves = 0;
2518
+ const groups = (nodes) => {
2519
+ for (const n of nodes) {
2520
+ if (n.kind !== "group") continue;
2521
+ maxGroupLeaves = Math.max(maxGroupLeaves, rows(n.nodes));
2522
+ groups(n.nodes);
2523
+ }
2524
+ };
2525
+ groups(screen.pinned);
2526
+ screen.tabs.forEach(groups);
2527
+ const pinned = rows(screen.pinned);
2528
+ const { values } = walkCosts(screen);
2529
+ return {
2530
+ ungroupedLeaves: screen.tabs.length ? Math.max(...screen.tabs.map((p) => pinned + rows(p))) : pinned,
2531
+ maxGroupLeaves,
2532
+ depth: screen.depth,
2533
+ maxActivations: screen.entry + (values.length ? Math.max(...values) : 0)
2534
+ };
2535
+ }
2536
+
2537
+ // src/button-link-pairing.ts
2538
+ var TEXT_ROLES = /* @__PURE__ */ new Set(["label", "text", "title", "cta", "button", "btn", "name"]);
2539
+ var LINK_ROLES = /* @__PURE__ */ new Set(["href", "link", "url", "to"]);
2540
+ var BUTTON_NOUNS = /* @__PURE__ */ new Set(["cta", "button", "btn"]);
2541
+ var TEXT_TYPES = /* @__PURE__ */ new Set(["text", "string"]);
2542
+ var LINK_TYPES = /* @__PURE__ */ new Set(["link", "url"]);
2543
+ var MEDIA = /image|img|photo|video|avatar|logo|icon|thumb|poster|embed|src|og|favicon/i;
2544
+ function keyWords(key) {
2545
+ const leaf = key.split(".").pop() ?? "";
2546
+ return leaf.replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s_-]+/).filter(Boolean).map((word) => word.toLowerCase());
2547
+ }
2548
+ function roleFromWords(candidate, words) {
2549
+ const type = (candidate.type ?? "").toLowerCase();
2550
+ const value = candidate.value;
2551
+ if (!(value === void 0 || value === null || typeof value === "string")) return null;
2552
+ if (!words.length) return null;
2553
+ const last = words[words.length - 1];
2554
+ const stem = words.slice(0, -1).join("_");
2555
+ const full = words.join("_");
2556
+ if (LINK_TYPES.has(type)) return { role: "link", stems: LINK_ROLES.has(last) ? [stem] : [stem, full] };
2557
+ if (!TEXT_TYPES.has(type)) return null;
2558
+ if (LINK_ROLES.has(last)) {
2559
+ if (MEDIA.test(candidate.key) || MEDIA.test(candidate.label ?? "")) return null;
2560
+ return { role: "link", stems: [stem] };
2561
+ }
2562
+ if (TEXT_ROLES.has(last)) return { role: "text", stems: BUTTON_NOUNS.has(last) ? [stem, full] : [stem] };
2563
+ return null;
2564
+ }
2565
+ function candidateRole(candidate) {
2566
+ const fromKey = roleFromWords(candidate, keyWords(candidate.key));
2567
+ if (fromKey) return fromKey;
2568
+ const label = candidate.label?.trim();
2569
+ if (!label) return null;
2570
+ const fromLabel = roleFromWords(candidate, keyWords(label.replace(/\s+/g, "_")));
2571
+ return fromLabel ? { role: fromLabel.role, stems: fromLabel.stems.map((stem) => `label:${stem}`) } : null;
2572
+ }
2573
+ function buttonLinkPairs(candidates) {
2574
+ const roles = candidates.map(candidateRole);
2575
+ const byStem = /* @__PURE__ */ new Map();
2576
+ roles.forEach((role, index) => {
2577
+ if (!role) return;
2578
+ for (const stem of new Set(role.stems)) {
2579
+ const bucket = byStem.get(stem) ?? { text: /* @__PURE__ */ new Set(), link: /* @__PURE__ */ new Set() };
2580
+ bucket[role.role].add(index);
2581
+ byStem.set(stem, bucket);
2582
+ }
2583
+ });
2584
+ const ambiguous = /* @__PURE__ */ new Set();
2585
+ const proposals = /* @__PURE__ */ new Map();
2586
+ for (const bucket of byStem.values()) {
2587
+ if (bucket.text.size + bucket.link.size >= 3) {
2588
+ for (const index of [...bucket.text, ...bucket.link]) ambiguous.add(index);
2589
+ continue;
2590
+ }
2591
+ if (bucket.text.size === 1 && bucket.link.size === 1) {
2592
+ const pair = [[...bucket.text][0], [...bucket.link][0]];
2593
+ proposals.set(pair.join(":"), pair);
2594
+ }
2595
+ }
2596
+ const uses = /* @__PURE__ */ new Map();
2597
+ for (const [text, link] of proposals.values()) {
2598
+ uses.set(text, (uses.get(text) ?? 0) + 1);
2599
+ uses.set(link, (uses.get(link) ?? 0) + 1);
2600
+ }
2601
+ return [...proposals.values()].filter(([t, l]) => !ambiguous.has(t) && !ambiguous.has(l) && uses.get(t) === 1 && uses.get(l) === 1).sort((a, b) => Math.min(...a) - Math.min(...b));
2602
+ }
2603
+
2159
2604
  // src/locator.ts
2160
2605
  var LANDMARK_SELECTOR = "header,nav,footer";
2161
2606
  var LANDMARK_TAGS = /* @__PURE__ */ new Set(["HEADER", "NAV", "FOOTER"]);
@@ -2220,6 +2665,9 @@ export {
2220
2665
  BLOCK_BINDINGS,
2221
2666
  COMPONENT_PROP_TYPES,
2222
2667
  DIALOG_SELECTOR,
2668
+ DOCK_BUDGET,
2669
+ DOCK_ICON_NAMES,
2670
+ DOCK_ICON_NAME_SET,
2223
2671
  FOOTER_SECTION_ID,
2224
2672
  LANDMARK_SELECTOR,
2225
2673
  LAYOUT_SECTION_ICONS,
@@ -2232,13 +2680,18 @@ export {
2232
2680
  SPACE_BOTTOM_TOKENS,
2233
2681
  SPACE_STEP_TOKENS,
2234
2682
  blockStyleToCss,
2683
+ buttonLinkPairs,
2684
+ candidateRole,
2235
2685
  componentInstanceAddresses,
2236
2686
  componentPropTargetKey,
2687
+ dockBudget,
2688
+ dockScreens,
2237
2689
  expandBlockBindings,
2238
2690
  formatPropsAttribute,
2239
2691
  getBlockType,
2240
2692
  isBlock,
2241
2693
  isChromeLandmark,
2694
+ keyWords,
2242
2695
  landmarkRegions,
2243
2696
  locatorFor,
2244
2697
  parsePropsAttribute,