@mulmoclaude/collection-plugin 0.13.1 → 0.14.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/vue.cjs CHANGED
@@ -27,6 +27,9 @@ let vue_i18n = require("vue-i18n");
27
27
  let vuedraggable = require("vuedraggable");
28
28
  vuedraggable = __toESM(vuedraggable, 1);
29
29
  let _mulmoclaude_core_remote_view = require("@mulmoclaude/core/remote-view");
30
+ let echarts = require("echarts");
31
+ echarts = __toESM(echarts, 1);
32
+ let _mulmoclaude_core_wiki = require("@mulmoclaude/core/wiki");
30
33
  let _mulmoclaude_core_translation_client = require("@mulmoclaude/core/translation/client");
31
34
  //#region src/vue/uiContext.ts
32
35
  var current = null;
@@ -99,6 +102,10 @@ var i18n = (0, vue_i18n.createI18n)({
99
102
  editable: "Editable",
100
103
  data: "Data"
101
104
  },
105
+ mapTab: "Map",
106
+ mapEmpty: "Nothing to map yet — the map draws itself as collections and the links between them appear.",
107
+ mapRecordCount: "{count} records",
108
+ mapMissingHint: "No collection with this slug — a relation points at it.",
102
109
  notFound: "Collection not found",
103
110
  loadFailed: "Failed to load",
104
111
  requiredField: "This field is required",
@@ -247,6 +254,10 @@ var i18n = (0, vue_i18n.createI18n)({
247
254
  editable: "編集可能",
248
255
  data: "データ"
249
256
  },
257
+ mapTab: "マップ",
258
+ mapEmpty: "まだ表示するものがありません。コレクションとその間のリンクが増えると、マップが自動的に描かれます。",
259
+ mapRecordCount: "{count} 件のレコード",
260
+ mapMissingHint: "このスラッグのコレクションは存在しません。リレーションが参照しています。",
250
261
  notFound: "コレクションが見つかりません",
251
262
  loadFailed: "読み込みに失敗しました",
252
263
  requiredField: "この項目は必須です",
@@ -395,6 +406,10 @@ var i18n = (0, vue_i18n.createI18n)({
395
406
  editable: "可编辑",
396
407
  data: "数据"
397
408
  },
409
+ mapTab: "地图",
410
+ mapEmpty: "暂无可显示的内容。随着集合及其之间的链接增多,地图会自动绘制。",
411
+ mapRecordCount: "{count} 条记录",
412
+ mapMissingHint: "不存在此 slug 的集合,但有关系指向它。",
398
413
  notFound: "未找到集合",
399
414
  loadFailed: "加载失败",
400
415
  requiredField: "此字段为必填项",
@@ -543,6 +558,10 @@ var i18n = (0, vue_i18n.createI18n)({
543
558
  editable: "편집 가능",
544
559
  data: "데이터"
545
560
  },
561
+ mapTab: "맵",
562
+ mapEmpty: "아직 표시할 내용이 없습니다. 컬렉션과 그 사이의 링크가 생기면 맵이 자동으로 그려집니다.",
563
+ mapRecordCount: "레코드 {count}개",
564
+ mapMissingHint: "이 슬러그의 컬렉션이 없습니다. 관계가 이를 참조하고 있습니다.",
546
565
  notFound: "컬렉션을 찾을 수 없습니다",
547
566
  loadFailed: "불러오기에 실패했습니다",
548
567
  requiredField: "이 필드는 필수입니다",
@@ -691,6 +710,10 @@ var i18n = (0, vue_i18n.createI18n)({
691
710
  editable: "Editables",
692
711
  data: "Datos"
693
712
  },
713
+ mapTab: "Mapa",
714
+ mapEmpty: "Nada que mostrar todavía: el mapa se dibuja solo a medida que aparecen colecciones y los enlaces entre ellas.",
715
+ mapRecordCount: "{count} registros",
716
+ mapMissingHint: "No existe una colección con este slug; una relación apunta a ella.",
694
717
  notFound: "Colección no encontrada",
695
718
  loadFailed: "Error al cargar",
696
719
  requiredField: "Este campo es obligatorio",
@@ -839,6 +862,10 @@ var i18n = (0, vue_i18n.createI18n)({
839
862
  editable: "Editáveis",
840
863
  data: "Dados"
841
864
  },
865
+ mapTab: "Mapa",
866
+ mapEmpty: "Nada para mostrar ainda — o mapa se desenha sozinho conforme coleções e os vínculos entre elas aparecem.",
867
+ mapRecordCount: "{count} registros",
868
+ mapMissingHint: "Nenhuma coleção com este slug — uma relação aponta para ela.",
842
869
  notFound: "Coleção não encontrada",
843
870
  loadFailed: "Falha ao carregar",
844
871
  requiredField: "Este campo é obrigatório",
@@ -987,6 +1014,10 @@ var i18n = (0, vue_i18n.createI18n)({
987
1014
  editable: "Modifiables",
988
1015
  data: "Données"
989
1016
  },
1017
+ mapTab: "Carte",
1018
+ mapEmpty: "Rien à afficher pour l'instant — la carte se dessine d'elle-même à mesure que les collections et leurs liens apparaissent.",
1019
+ mapRecordCount: "{count} enregistrements",
1020
+ mapMissingHint: "Aucune collection avec ce slug — une relation pointe vers elle.",
990
1021
  notFound: "Collection introuvable",
991
1022
  loadFailed: "Échec du chargement",
992
1023
  requiredField: "Ce champ est obligatoire",
@@ -1135,6 +1166,10 @@ var i18n = (0, vue_i18n.createI18n)({
1135
1166
  editable: "Bearbeitbar",
1136
1167
  data: "Daten"
1137
1168
  },
1169
+ mapTab: "Karte",
1170
+ mapEmpty: "Noch nichts zu zeigen — die Karte entsteht von selbst, sobald Sammlungen und ihre Verknüpfungen entstehen.",
1171
+ mapRecordCount: "{count} Einträge",
1172
+ mapMissingHint: "Keine Sammlung mit diesem Slug — eine Relation verweist darauf.",
1138
1173
  notFound: "Sammlung nicht gefunden",
1139
1174
  loadFailed: "Laden fehlgeschlagen",
1140
1175
  requiredField: "Dieses Feld ist erforderlich",
@@ -1349,8 +1384,8 @@ function isExternalUrl(value) {
1349
1384
  return typeof value === "string" && /^https?:\/\//i.test(value);
1350
1385
  }
1351
1386
  function detailText(value) {
1352
- if (value === void 0 || value === null || value === "") return EM_DASH;
1353
- return String(value);
1387
+ const text = (0, _mulmoclaude_core_collection.fieldText)(value, EM_DASH);
1388
+ return text === "" ? EM_DASH : text;
1354
1389
  }
1355
1390
  function formatCell(value, type) {
1356
1391
  if (value === void 0 || value === null || value === "") return EM_DASH;
@@ -1374,7 +1409,7 @@ function resolveCurrency(field, record) {
1374
1409
  function formatMoney(value, currency, displayLocale) {
1375
1410
  if (value === void 0 || value === "") return EM_DASH;
1376
1411
  const amount = typeof value === "number" ? value : Number(value);
1377
- if (!Number.isFinite(amount)) return String(value);
1412
+ if (!Number.isFinite(amount)) return (0, _mulmoclaude_core_collection.fieldText)(value, EM_DASH);
1378
1413
  const currencyCode = currency && currency.length > 0 ? currency : DEFAULT_CURRENCY;
1379
1414
  try {
1380
1415
  return new Intl.NumberFormat(displayLocale, {
@@ -1477,7 +1512,7 @@ function buildEmbedOptions(schema, items) {
1477
1512
  const { fields, primaryKey } = schema;
1478
1513
  const displayField = displayFieldFor(fields, primaryKey);
1479
1514
  return items.map((item) => {
1480
- const slug = String(item[primaryKey] ?? "");
1515
+ const slug = (0, _mulmoclaude_core_collection.fieldText)(item[primaryKey]);
1481
1516
  const labelRaw = item[displayField];
1482
1517
  return {
1483
1518
  slug,
@@ -1487,13 +1522,13 @@ function buildEmbedOptions(schema, items) {
1487
1522
  }
1488
1523
  //#endregion
1489
1524
  //#region src/vue/components/CollectionMutateParamsModal.vue?vue&type=script&setup=true&lang.ts
1490
- var _hoisted_1$16 = { class: "flex items-center justify-between px-6 pt-5 pb-3" };
1491
- var _hoisted_2$15 = { class: "text-sm font-bold text-slate-800 flex items-center gap-1.5" };
1492
- var _hoisted_3$15 = {
1525
+ var _hoisted_1$17 = { class: "flex items-center justify-between px-6 pt-5 pb-3" };
1526
+ var _hoisted_2$16 = { class: "text-sm font-bold text-slate-800 flex items-center gap-1.5" };
1527
+ var _hoisted_3$16 = {
1493
1528
  key: 0,
1494
1529
  class: "material-icons text-base text-indigo-600"
1495
1530
  };
1496
- var _hoisted_4$15 = ["aria-label"];
1531
+ var _hoisted_4$16 = ["aria-label"];
1497
1532
  var _hoisted_5$14 = { class: "flex flex-col gap-4 px-6 pb-2" };
1498
1533
  var _hoisted_6$13 = ["for"];
1499
1534
  var _hoisted_7$11 = {
@@ -1591,13 +1626,13 @@ var CollectionMutateParamsModal_default = /* @__PURE__ */ (0, vue.defineComponen
1591
1626
  "data-testid": "collections-mutate-modal",
1592
1627
  onSubmit: (0, vue.withModifiers)(submit, ["prevent"])
1593
1628
  }, [
1594
- (0, vue.createElementVNode)("div", _hoisted_1$16, [(0, vue.createElementVNode)("h2", _hoisted_2$15, [__props.action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_3$15, (0, vue.toDisplayString)(__props.action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.action.label), 1)]), (0, vue.createElementVNode)("button", {
1629
+ (0, vue.createElementVNode)("div", _hoisted_1$17, [(0, vue.createElementVNode)("h2", _hoisted_2$16, [__props.action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_3$16, (0, vue.toDisplayString)(__props.action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.action.label), 1)]), (0, vue.createElementVNode)("button", {
1595
1630
  type: "button",
1596
1631
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-100 hover:text-slate-600 transition-colors",
1597
1632
  "aria-label": (0, vue.unref)(t)("common.close"),
1598
1633
  "data-testid": "collections-mutate-close",
1599
1634
  onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
1600
- }, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$15)]),
1635
+ }, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$16)]),
1601
1636
  (0, vue.createElementVNode)("div", _hoisted_5$14, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.action.params, (spec, key) => {
1602
1637
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
1603
1638
  key,
@@ -1662,13 +1697,13 @@ var CollectionMutateParamsModal_default = /* @__PURE__ */ (0, vue.defineComponen
1662
1697
  });
1663
1698
  //#endregion
1664
1699
  //#region src/vue/components/CollectionCalendarView.vue?vue&type=script&setup=true&lang.ts
1665
- var _hoisted_1$15 = {
1700
+ var _hoisted_1$16 = {
1666
1701
  class: "flex flex-col gap-3",
1667
1702
  "data-testid": "collection-calendar"
1668
1703
  };
1669
- var _hoisted_2$14 = { class: "flex items-center gap-2" };
1670
- var _hoisted_3$14 = ["aria-label"];
1671
- var _hoisted_4$14 = ["aria-label"];
1704
+ var _hoisted_2$15 = { class: "flex items-center gap-2" };
1705
+ var _hoisted_3$15 = ["aria-label"];
1706
+ var _hoisted_4$15 = ["aria-label"];
1672
1707
  var _hoisted_5$13 = {
1673
1708
  class: "text-sm font-bold text-slate-800 flex-1",
1674
1709
  "data-testid": "collection-calendar-month"
@@ -1803,22 +1838,22 @@ var CollectionCalendarView_default = /* @__PURE__ */ (0, vue.defineComponent)({
1803
1838
  viewMonth.value = now.getMonth() + 1;
1804
1839
  }
1805
1840
  return (_ctx, _cache) => {
1806
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$15, [
1807
- (0, vue.createElementVNode)("div", _hoisted_2$14, [
1841
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$16, [
1842
+ (0, vue.createElementVNode)("div", _hoisted_2$15, [
1808
1843
  (0, vue.createElementVNode)("button", {
1809
1844
  type: "button",
1810
1845
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
1811
1846
  "aria-label": (0, vue.unref)(t)("collectionsView.calendarPrevMonth"),
1812
1847
  "data-testid": "collection-calendar-prev",
1813
1848
  onClick: _cache[0] || (_cache[0] = ($event) => stepMonth(-1))
1814
- }, [..._cache[2] || (_cache[2] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$14),
1849
+ }, [..._cache[2] || (_cache[2] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$15),
1815
1850
  (0, vue.createElementVNode)("button", {
1816
1851
  type: "button",
1817
1852
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
1818
1853
  "aria-label": (0, vue.unref)(t)("collectionsView.calendarNextMonth"),
1819
1854
  "data-testid": "collection-calendar-next",
1820
1855
  onClick: _cache[1] || (_cache[1] = ($event) => stepMonth(1))
1821
- }, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$14),
1856
+ }, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$15),
1822
1857
  (0, vue.createElementVNode)("h3", _hoisted_5$13, (0, vue.toDisplayString)(monthLabel.value), 1),
1823
1858
  (0, vue.createElementVNode)("button", {
1824
1859
  type: "button",
@@ -1868,13 +1903,13 @@ var CollectionCalendarView_default = /* @__PURE__ */ (0, vue.defineComponent)({
1868
1903
  });
1869
1904
  //#endregion
1870
1905
  //#region src/vue/components/CollectionDayView.vue?vue&type=script&setup=true&lang.ts
1871
- var _hoisted_1$14 = { class: "flex items-center gap-2 border-b border-slate-200 px-4 py-3" };
1872
- var _hoisted_2$13 = {
1906
+ var _hoisted_1$15 = { class: "flex items-center gap-2 border-b border-slate-200 px-4 py-3" };
1907
+ var _hoisted_2$14 = {
1873
1908
  class: "flex-1 text-sm font-bold text-slate-800",
1874
1909
  "data-testid": "collection-day-view-title"
1875
1910
  };
1876
- var _hoisted_3$13 = ["aria-label"];
1877
- var _hoisted_4$13 = ["aria-label"];
1911
+ var _hoisted_3$14 = ["aria-label"];
1912
+ var _hoisted_4$14 = ["aria-label"];
1878
1913
  var _hoisted_5$12 = {
1879
1914
  key: 0,
1880
1915
  class: "px-4 py-10 text-center text-sm text-slate-400"
@@ -2062,8 +2097,8 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2062
2097
  role: "dialog",
2063
2098
  "aria-modal": "true"
2064
2099
  }, [(0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["flex min-h-0 flex-col", __props.showDetail ? "w-80 shrink-0 border-r border-slate-200" : "w-full"]) }, [
2065
- (0, vue.createElementVNode)("div", _hoisted_1$14, [
2066
- (0, vue.createElementVNode)("h3", _hoisted_2$13, (0, vue.toDisplayString)(dayLabel.value), 1),
2100
+ (0, vue.createElementVNode)("div", _hoisted_1$15, [
2101
+ (0, vue.createElementVNode)("h3", _hoisted_2$14, (0, vue.toDisplayString)(dayLabel.value), 1),
2067
2102
  __props.canCreate ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
2068
2103
  key: 0,
2069
2104
  type: "button",
@@ -2071,14 +2106,14 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2071
2106
  "aria-label": (0, vue.unref)(t)("collectionsView.calendarCreateOn", { date: dayKey.value }),
2072
2107
  "data-testid": "collection-day-view-create",
2073
2108
  onClick: onCreate
2074
- }, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$13)) : (0, vue.createCommentVNode)("", true),
2109
+ }, [..._cache[3] || (_cache[3] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$14)) : (0, vue.createCommentVNode)("", true),
2075
2110
  (0, vue.createElementVNode)("button", {
2076
2111
  type: "button",
2077
2112
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
2078
2113
  "aria-label": (0, vue.unref)(t)("collectionsView.dayViewClose"),
2079
2114
  "data-testid": "collection-day-view-close",
2080
2115
  onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
2081
- }, [..._cache[4] || (_cache[4] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$13)
2116
+ }, [..._cache[4] || (_cache[4] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$14)
2082
2117
  ]),
2083
2118
  timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_5$12, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dayViewEmpty")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2084
2119
  key: 1,
@@ -2129,13 +2164,13 @@ var CollectionDayView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2129
2164
  });
2130
2165
  //#endregion
2131
2166
  //#region src/vue/components/CollectionKanbanView.vue?vue&type=script&setup=true&lang.ts
2132
- var _hoisted_1$13 = {
2167
+ var _hoisted_1$14 = {
2133
2168
  class: "h-full overflow-x-auto overflow-y-hidden",
2134
2169
  "data-testid": "collection-kanban"
2135
2170
  };
2136
- var _hoisted_2$12 = { class: "flex gap-3 h-full p-1 min-w-max" };
2137
- var _hoisted_3$12 = ["data-testid"];
2138
- var _hoisted_4$12 = { class: "flex items-center justify-between px-3 py-2 border-b border-slate-200" };
2171
+ var _hoisted_2$13 = { class: "flex gap-3 h-full p-1 min-w-max" };
2172
+ var _hoisted_3$13 = ["data-testid"];
2173
+ var _hoisted_4$13 = { class: "flex items-center justify-between px-3 py-2 border-b border-slate-200" };
2139
2174
  var _hoisted_5$11 = { class: "flex items-center gap-2 min-w-0" };
2140
2175
  var _hoisted_6$10 = ["title"];
2141
2176
  var _hoisted_7$8 = { class: "text-[11px] text-slate-400 shrink-0" };
@@ -2257,12 +2292,12 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2257
2292
  emit("move", itemId(item), next);
2258
2293
  }
2259
2294
  return (_ctx, _cache) => {
2260
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$13, [(0, vue.createElementVNode)("div", _hoisted_2$12, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(columns.value, (column) => {
2295
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$14, [(0, vue.createElementVNode)("div", _hoisted_2$13, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(columns.value, (column) => {
2261
2296
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2262
2297
  key: column.value,
2263
2298
  "data-testid": `collection-kanban-column-${column.value || "uncategorized"}`,
2264
2299
  class: "w-72 shrink-0 flex flex-col bg-slate-100 rounded-lg"
2265
- }, [(0, vue.createElementVNode)("div", _hoisted_4$12, [(0, vue.createElementVNode)("div", _hoisted_5$11, [(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["w-2 h-2 rounded-full shrink-0", (0, vue.unref)(_mulmoclaude_core_collection.resolveEnumColor)(__props.schema, __props.groupField, column.value).dot]) }, null, 2), (0, vue.createElementVNode)("span", {
2300
+ }, [(0, vue.createElementVNode)("div", _hoisted_4$13, [(0, vue.createElementVNode)("div", _hoisted_5$11, [(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["w-2 h-2 rounded-full shrink-0", (0, vue.unref)(_mulmoclaude_core_collection.resolveEnumColor)(__props.schema, __props.groupField, column.value).dot]) }, null, 2), (0, vue.createElementVNode)("span", {
2266
2301
  class: "font-semibold text-xs text-slate-600 truncate",
2267
2302
  title: column.label
2268
2303
  }, (0, vue.toDisplayString)(column.label), 9, _hoisted_6$10)]), (0, vue.createElementVNode)("span", _hoisted_7$8, (0, vue.toDisplayString)(itemsByColumn(column.value).length), 1)]), (0, vue.createVNode)((0, vue.unref)(vuedraggable.default), {
@@ -2298,7 +2333,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2298
2333
  "item-key",
2299
2334
  "disabled",
2300
2335
  "onChange"
2301
- ])], 8, _hoisted_3$12);
2336
+ ])], 8, _hoisted_3$13);
2302
2337
  }), 128))])]);
2303
2338
  };
2304
2339
  }
@@ -2328,10 +2363,10 @@ function activatePathLink(event, path, stop = false) {
2328
2363
  }
2329
2364
  //#endregion
2330
2365
  //#region src/vue/components/CollectionBacklinksView.vue?vue&type=script&setup=true&lang.ts
2331
- var _hoisted_1$12 = ["data-testid"];
2332
- var _hoisted_2$11 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2333
- var _hoisted_3$11 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2334
- var _hoisted_4$11 = { class: "divide-y divide-slate-100" };
2366
+ var _hoisted_1$13 = ["data-testid"];
2367
+ var _hoisted_2$12 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2368
+ var _hoisted_3$12 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2369
+ var _hoisted_4$12 = { class: "divide-y divide-slate-100" };
2335
2370
  var _hoisted_5$10 = [
2336
2371
  "data-testid",
2337
2372
  "onClick",
@@ -2353,12 +2388,12 @@ var CollectionBacklinksView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2353
2388
  key: 0,
2354
2389
  class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1",
2355
2390
  "data-testid": `collections-backlinks-${__props.fieldKey}`
2356
- }, [(0, vue.createElementVNode)("table", _hoisted_2$11, [(0, vue.createElementVNode)("thead", _hoisted_3$11, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.columns, (column) => {
2391
+ }, [(0, vue.createElementVNode)("table", _hoisted_2$12, [(0, vue.createElementVNode)("thead", _hoisted_3$12, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.columns, (column) => {
2357
2392
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
2358
2393
  key: column.key,
2359
2394
  class: "text-left px-4 py-2 font-bold"
2360
2395
  }, (0, vue.toDisplayString)(column.label), 1);
2361
- }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_4$11, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.rows, (row) => {
2396
+ }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_4$12, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.rows, (row) => {
2362
2397
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
2363
2398
  key: row.id,
2364
2399
  class: "group hover:bg-indigo-50/30 cursor-pointer transition-colors",
@@ -2373,7 +2408,7 @@ var CollectionBacklinksView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2373
2408
  class: "px-4 py-2 align-middle font-medium"
2374
2409
  }, [(0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(cellIdx === 0 ? "text-indigo-600 group-hover:text-indigo-800 font-bold" : "") }, (0, vue.toDisplayString)(cell), 3)]);
2375
2410
  }), 128))], 40, _hoisted_5$10);
2376
- }), 128))])])], 8, _hoisted_1$12)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
2411
+ }), 128))])])], 8, _hoisted_1$13)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
2377
2412
  key: 1,
2378
2413
  class: "text-slate-400 italic",
2379
2414
  "data-testid": `collections-backlinks-${__props.fieldKey}`
@@ -2383,14 +2418,14 @@ var CollectionBacklinksView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2383
2418
  });
2384
2419
  //#endregion
2385
2420
  //#region src/vue/components/CollectionEmbedView.vue?vue&type=script&setup=true&lang.ts
2386
- var _hoisted_1$11 = [
2421
+ var _hoisted_1$12 = [
2387
2422
  "href",
2388
2423
  "tabindex",
2389
2424
  "data-testid"
2390
2425
  ];
2391
- var _hoisted_2$10 = { class: "flex items-center justify-between text-[10px] font-bold text-indigo-600/90 tracking-wider uppercase" };
2392
- var _hoisted_3$10 = { class: "flex items-center gap-1.5" };
2393
- var _hoisted_4$10 = { class: "bg-indigo-100/60 text-indigo-700 px-1.5 py-0.5 rounded font-mono font-medium lowercase" };
2426
+ var _hoisted_2$11 = { class: "flex items-center justify-between text-[10px] font-bold text-indigo-600/90 tracking-wider uppercase" };
2427
+ var _hoisted_3$11 = { class: "flex items-center gap-1.5" };
2428
+ var _hoisted_4$11 = { class: "bg-indigo-100/60 text-indigo-700 px-1.5 py-0.5 rounded font-mono font-medium lowercase" };
2394
2429
  var _hoisted_5$9 = { class: "grid gap-x-4 gap-y-3 grid-cols-2" };
2395
2430
  var _hoisted_6$8 = { class: "text-[10px] font-semibold text-slate-400 uppercase tracking-wide" };
2396
2431
  var _hoisted_7$7 = ["data-testid"];
@@ -2436,7 +2471,7 @@ var CollectionEmbedView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2436
2471
  onKeydown: [_cache[1] || (_cache[1] = (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId), ["enter"])), _cache[2] || (_cache[2] = (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId), ["space"]))]
2437
2472
  }, [
2438
2473
  _cache[7] || (_cache[7] = (0, vue.createElementVNode)("div", { class: "absolute left-0 top-0 bottom-0 w-1 bg-indigo-500 rounded-l-xl transition-all duration-300 group-hover:w-1.5 group-hover:bg-indigo-600" }, null, -1)),
2439
- (0, vue.createElementVNode)("div", _hoisted_2$10, [(0, vue.createElementVNode)("div", _hoisted_3$10, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "link", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.view.targetSlug), 1)]), (0, vue.createElementVNode)("span", _hoisted_4$10, (0, vue.toDisplayString)(__props.view.recordId), 1)]),
2474
+ (0, vue.createElementVNode)("div", _hoisted_2$11, [(0, vue.createElementVNode)("div", _hoisted_3$11, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "link", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.view.targetSlug), 1)]), (0, vue.createElementVNode)("span", _hoisted_4$11, (0, vue.toDisplayString)(__props.view.recordId), 1)]),
2440
2475
  (0, vue.createElementVNode)("div", _hoisted_5$9, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.view.rows, (row) => {
2441
2476
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2442
2477
  key: row.key,
@@ -2446,7 +2481,7 @@ var CollectionEmbedView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2446
2481
  "data-testid": `collections-embed-${__props.fieldKey}-${row.key}`
2447
2482
  }, [row.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row.value === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$7, "check_circle")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_9$7, "—"))], 64)) : row.type === "markdown" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_10$7, (0, vue.toDisplayString)(row.display), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_11$7, (0, vue.toDisplayString)(row.display), 1))], 8, _hoisted_7$7)]);
2448
2483
  }), 128))])
2449
- ], 40, _hoisted_1$11)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2484
+ ], 40, _hoisted_1$12)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2450
2485
  key: 1,
2451
2486
  class: "relative rounded-xl border border-red-100 bg-red-50/30 p-4 pl-5 shadow-sm",
2452
2487
  "data-testid": `collections-embed-${__props.fieldKey}`
@@ -2474,10 +2509,10 @@ var CollectionEmbedView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2474
2509
  });
2475
2510
  //#endregion
2476
2511
  //#region src/vue/components/CollectionRecordPanel.vue?vue&type=script&setup=true&lang.ts
2477
- var _hoisted_1$10 = { class: "flex items-center gap-2 mb-4" };
2478
- var _hoisted_2$9 = { class: "flex-1 min-w-0" };
2479
- var _hoisted_3$9 = { class: "block text-[9px] font-bold text-slate-400 uppercase tracking-wider" };
2480
- var _hoisted_4$9 = ["data-testid"];
2512
+ var _hoisted_1$11 = { class: "flex items-center gap-2 mb-4" };
2513
+ var _hoisted_2$10 = { class: "flex-1 min-w-0" };
2514
+ var _hoisted_3$10 = { class: "block text-[9px] font-bold text-slate-400 uppercase tracking-wider" };
2515
+ var _hoisted_4$10 = ["data-testid"];
2481
2516
  var _hoisted_5$8 = ["disabled"];
2482
2517
  var _hoisted_6$7 = {
2483
2518
  key: 1,
@@ -2855,10 +2890,10 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
2855
2890
  onSubmit: _cache[5] || (_cache[5] = (0, vue.withModifiers)(($event) => emit("submit"), ["prevent"]))
2856
2891
  }, {
2857
2892
  default: (0, vue.withCtx)(() => [
2858
- (0, vue.createElementVNode)("div", _hoisted_1$10, [(0, vue.createElementVNode)("div", _hoisted_2$9, [(0, vue.createElementVNode)("span", _hoisted_3$9, (0, vue.toDisplayString)(__props.collection.title), 1), (0, vue.createElementVNode)("h2", {
2893
+ (0, vue.createElementVNode)("div", _hoisted_1$11, [(0, vue.createElementVNode)("div", _hoisted_2$10, [(0, vue.createElementVNode)("span", _hoisted_3$10, (0, vue.toDisplayString)(__props.collection.title), 1), (0, vue.createElementVNode)("h2", {
2859
2894
  class: "text-base font-bold text-slate-800 truncate",
2860
2895
  "data-testid": editing.value ? "collections-edit-title" : "collections-detail-title"
2861
- }, (0, vue.toDisplayString)(headerTitle.value), 9, _hoisted_4$9)]), editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createElementVNode)("button", {
2896
+ }, (0, vue.toDisplayString)(headerTitle.value), 9, _hoisted_4$10)]), editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createElementVNode)("button", {
2862
2897
  type: "button",
2863
2898
  class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
2864
2899
  "data-testid": "collections-editor-cancel",
@@ -3167,13 +3202,13 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3167
3202
  });
3168
3203
  //#endregion
3169
3204
  //#region src/vue/components/CollectionViewConfigModal.vue?vue&type=script&setup=true&lang.ts
3170
- var _hoisted_1$9 = {
3205
+ var _hoisted_1$10 = {
3171
3206
  "data-testid": "collection-config-modal",
3172
3207
  class: "flex flex-col overflow-hidden"
3173
3208
  };
3174
- var _hoisted_2$8 = { class: "flex items-center justify-between gap-2 border-b border-slate-100 px-5 py-3" };
3175
- var _hoisted_3$8 = { class: "text-sm font-bold text-slate-700" };
3176
- var _hoisted_4$8 = ["title", "aria-label"];
3209
+ var _hoisted_2$9 = { class: "flex items-center justify-between gap-2 border-b border-slate-100 px-5 py-3" };
3210
+ var _hoisted_3$9 = { class: "text-sm font-bold text-slate-700" };
3211
+ var _hoisted_4$9 = ["title", "aria-label"];
3177
3212
  var _hoisted_5$7 = { class: "overflow-y-auto px-5 py-4" };
3178
3213
  var _hoisted_6$6 = { class: "mb-2 text-[10px] font-bold uppercase tracking-wider text-slate-400" };
3179
3214
  var _hoisted_7$5 = {
@@ -3239,14 +3274,14 @@ var CollectionViewConfigModal_default = /* @__PURE__ */ (0, vue.defineComponent)
3239
3274
  }
3240
3275
  return (_ctx, _cache) => {
3241
3276
  return (0, vue.openBlock)(), (0, vue.createBlock)(CollectionRecordModal_default, { onClose: _cache[1] || (_cache[1] = ($event) => emit("close")) }, {
3242
- default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_1$9, [(0, vue.createElementVNode)("header", _hoisted_2$8, [(0, vue.createElementVNode)("h2", _hoisted_3$8, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.config.title", { title: __props.title })), 1), (0, vue.createElementVNode)("button", {
3277
+ default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_1$10, [(0, vue.createElementVNode)("header", _hoisted_2$9, [(0, vue.createElementVNode)("h2", _hoisted_3$9, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.config.title", { title: __props.title })), 1), (0, vue.createElementVNode)("button", {
3243
3278
  type: "button",
3244
3279
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-50 hover:text-slate-600",
3245
3280
  title: (0, vue.unref)(t)("common.close"),
3246
3281
  "aria-label": (0, vue.unref)(t)("common.close"),
3247
3282
  "data-testid": "collection-config-close",
3248
3283
  onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
3249
- }, [..._cache[2] || (_cache[2] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_4$8)]), (0, vue.createElementVNode)("div", _hoisted_5$7, [
3284
+ }, [..._cache[2] || (_cache[2] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_4$9)]), (0, vue.createElementVNode)("div", _hoisted_5$7, [
3250
3285
  (0, vue.createElementVNode)("h3", _hoisted_6$6, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.config.viewsHeading")), 1),
3251
3286
  error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_7$5, (0, vue.toDisplayString)(error.value), 1)) : (0, vue.createCommentVNode)("", true),
3252
3287
  __props.views.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("ul", _hoisted_8$5, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.views, (view) => {
@@ -3275,19 +3310,19 @@ var CollectionViewConfigModal_default = /* @__PURE__ */ (0, vue.defineComponent)
3275
3310
  });
3276
3311
  //#endregion
3277
3312
  //#region src/vue/components/CollectionCustomView.vue?vue&type=script&setup=true&lang.ts
3278
- var _hoisted_1$8 = { class: "custom-view-container" };
3279
- var _hoisted_2$7 = {
3313
+ var _hoisted_1$9 = { class: "custom-view-container" };
3314
+ var _hoisted_2$8 = {
3280
3315
  key: 0,
3281
3316
  class: "custom-view-message",
3282
3317
  role: "alert",
3283
3318
  "data-testid": "collection-custom-view-error"
3284
3319
  };
3285
- var _hoisted_3$7 = {
3320
+ var _hoisted_3$8 = {
3286
3321
  key: 1,
3287
3322
  class: "custom-view-message",
3288
3323
  "data-testid": "collection-custom-view-loading"
3289
3324
  };
3290
- var _hoisted_4$7 = ["title", "srcdoc"];
3325
+ var _hoisted_4$8 = ["title", "srcdoc"];
3291
3326
  var REMINT_LEAD_MS = 6e4;
3292
3327
  var MIN_REMINT_DELAY_MS = 1e4;
3293
3328
  var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ (0, vue.defineComponent)({
@@ -3409,7 +3444,7 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /*@__PURE
3409
3444
  window.removeEventListener("message", onWindowMessage);
3410
3445
  });
3411
3446
  return (_ctx, _cache) => {
3412
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$8, [error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$7, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$7, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("iframe", {
3447
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$9, [error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$8, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$8, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("iframe", {
3413
3448
  ref_key: "iframeEl",
3414
3449
  ref: iframeEl,
3415
3450
  key: __props.view.id,
@@ -3418,7 +3453,7 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /*@__PURE
3418
3453
  srcdoc: srcdoc.value,
3419
3454
  sandbox: "allow-scripts allow-popups allow-popups-to-escape-sandbox allow-downloads",
3420
3455
  class: "w-full h-full border-0"
3421
- }, null, 8, _hoisted_4$7)) : (0, vue.createCommentVNode)("", true)]);
3456
+ }, null, 8, _hoisted_4$8)) : (0, vue.createCommentVNode)("", true)]);
3422
3457
  };
3423
3458
  }
3424
3459
  });
@@ -3434,22 +3469,22 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
3434
3469
  var CollectionCustomView_default = /*#__PURE__*/ _plugin_vue_export_helper_default(CollectionCustomView_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-02ff1e01"]]);
3435
3470
  //#endregion
3436
3471
  //#region src/vue/components/CollectionRemoteViewPreview.vue?vue&type=script&setup=true&lang.ts
3437
- var _hoisted_1$7 = {
3472
+ var _hoisted_1$8 = {
3438
3473
  class: "remote-preview-container",
3439
3474
  "data-testid": "collection-remote-view-preview"
3440
3475
  };
3441
- var _hoisted_2$6 = {
3476
+ var _hoisted_2$7 = {
3442
3477
  key: 0,
3443
3478
  class: "remote-preview-message",
3444
3479
  role: "alert",
3445
3480
  "data-testid": "collection-remote-view-error"
3446
3481
  };
3447
- var _hoisted_3$6 = {
3482
+ var _hoisted_3$7 = {
3448
3483
  key: 1,
3449
3484
  class: "remote-preview-message",
3450
3485
  "data-testid": "collection-remote-view-loading"
3451
3486
  };
3452
- var _hoisted_4$6 = { class: "phone-frame" };
3487
+ var _hoisted_4$7 = { class: "phone-frame" };
3453
3488
  var _hoisted_5$6 = ["title", "srcdoc"];
3454
3489
  var _hoisted_6$5 = {
3455
3490
  class: "remote-preview-caption",
@@ -3546,7 +3581,7 @@ var CollectionRemoteViewPreview_default = /*#__PURE__*/ _plugin_vue_export_helpe
3546
3581
  (0, vue.onMounted)(() => window.addEventListener("message", onWindowMessage));
3547
3582
  (0, vue.onBeforeUnmount)(() => window.removeEventListener("message", onWindowMessage));
3548
3583
  return (_ctx, _cache) => {
3549
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$7, [error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$6, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$6, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [(0, vue.createElementVNode)("div", _hoisted_4$6, [((0, vue.openBlock)(), (0, vue.createElementBlock)("iframe", {
3584
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$8, [error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$7, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$7, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [(0, vue.createElementVNode)("div", _hoisted_4$7, [((0, vue.openBlock)(), (0, vue.createElementBlock)("iframe", {
3550
3585
  ref_key: "iframeEl",
3551
3586
  ref: iframeEl,
3552
3587
  key: __props.view.id,
@@ -3673,7 +3708,7 @@ function resolveEmbed(field, record, embedCache) {
3673
3708
  schema: null,
3674
3709
  item: null
3675
3710
  };
3676
- const item = data.items.find((entry) => String(entry[data.schema.primaryKey] ?? "") === targetId) ?? null;
3711
+ const item = data.items.find((entry) => (0, _mulmoclaude_core_collection.fieldText)(entry[data.schema.primaryKey]) === targetId) ?? null;
3677
3712
  return {
3678
3713
  schema: data.schema,
3679
3714
  item
@@ -3755,8 +3790,8 @@ function buildBacklinksViews(schema, embedCache, record, locale) {
3755
3790
  out[key] = {
3756
3791
  found: true,
3757
3792
  columns,
3758
- rows: (0, _mulmoclaude_core_collection.backlinkRows)(field, String(record?.[schema.primaryKey] ?? ""), derivedSourceItems(embedCache, field.from) ?? []).map((row) => ({
3759
- id: String(row[data.schema.primaryKey] ?? ""),
3793
+ rows: (0, _mulmoclaude_core_collection.backlinkRows)(field, (0, _mulmoclaude_core_collection.fieldText)(record?.[schema.primaryKey]), derivedSourceItems(embedCache, field.from) ?? []).map((row) => ({
3794
+ id: (0, _mulmoclaude_core_collection.fieldText)(row[data.schema.primaryKey]),
3760
3795
  cells: columns.map((column) => formatBacklinkCell(data.schema.fields[column.key], row[column.key], row, locale))
3761
3796
  })),
3762
3797
  fromSlug: field.from
@@ -3789,7 +3824,7 @@ function rollupValueFor(field, record, schema, embedCache) {
3789
3824
  if (field.type !== "rollup" || !schema || !record) return null;
3790
3825
  const items = derivedSourceItems(embedCache, field.from);
3791
3826
  if (items === null) return null;
3792
- return (0, _mulmoclaude_core_collection.rollupValue)(field, String(record[schema.primaryKey] ?? ""), items);
3827
+ return (0, _mulmoclaude_core_collection.rollupValue)(field, (0, _mulmoclaude_core_collection.fieldText)(record[schema.primaryKey]), items);
3793
3828
  }
3794
3829
  /** Display string for a rollup cell: the aggregate as a plain number,
3795
3830
  * em-dash when the source collection couldn't be resolved. */
@@ -3987,13 +4022,13 @@ function writeCollectionFlagFilters(slug, filters) {
3987
4022
  }
3988
4023
  //#endregion
3989
4024
  //#region src/vue/components/CollectionView.vue?vue&type=script&setup=true&lang.ts
3990
- var _hoisted_1$6 = { class: "h-full flex flex-col bg-slate-50/30" };
3991
- var _hoisted_2$5 = {
4025
+ var _hoisted_1$7 = { class: "h-full flex flex-col bg-slate-50/30" };
4026
+ var _hoisted_2$6 = {
3992
4027
  key: 0,
3993
4028
  class: "flex items-center gap-3 px-6 py-2 border-b border-slate-200 bg-white"
3994
4029
  };
3995
- var _hoisted_3$5 = ["title", "aria-label"];
3996
- var _hoisted_4$5 = {
4030
+ var _hoisted_3$6 = ["title", "aria-label"];
4031
+ var _hoisted_4$6 = {
3997
4032
  key: 1,
3998
4033
  class: "h-9 w-9 flex items-center justify-center rounded-xl bg-indigo-50 text-indigo-600 border border-indigo-100"
3999
4034
  };
@@ -4485,8 +4520,18 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4485
4520
  const activeFlagFilterCount = (0, vue.computed)(() => flagChips.value.filter((chip) => flagFilterMode(chip.key) !== void 0).length);
4486
4521
  const filterMenuOpen = (0, vue.ref)(false);
4487
4522
  const filterMenuRef = (0, vue.ref)(null);
4523
+ /** Shadow-DOM-safe "did this event land inside the element?". A document-level
4524
+ * listener sees `event.target` retargeted to the shadow HOST when the
4525
+ * component is mounted in a shadow root (MulmoTerminal's PluginFrame), so
4526
+ * `element.contains()` is always false there and the menu closes on the
4527
+ * mousedown before the inner button's click can fire. `composedPath()` still
4528
+ * lists the element for open shadow trees — and in the light DOM too, so both
4529
+ * hosts share this one test. */
4530
+ function eventInsideElement(event, element) {
4531
+ return element !== null && event.composedPath().includes(element);
4532
+ }
4488
4533
  function closeFilterMenuOnOutsideClick(event) {
4489
- if (!filterMenuRef.value?.contains(event.target)) filterMenuOpen.value = false;
4534
+ if (!eventInsideElement(event, filterMenuRef.value)) filterMenuOpen.value = false;
4490
4535
  }
4491
4536
  (0, vue.watch)(filterMenuOpen, (open) => {
4492
4537
  if (open) document.addEventListener("mousedown", closeFilterMenuOnOutsideClick);
@@ -5015,7 +5060,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5015
5060
  addMenuOpen.value = !addMenuOpen.value;
5016
5061
  }
5017
5062
  function closeAddMenuOnOutsideClick(event) {
5018
- if (!addMenuRef.value?.contains(event.target)) addMenuOpen.value = false;
5063
+ if (!eventInsideElement(event, addMenuRef.value)) addMenuOpen.value = false;
5019
5064
  }
5020
5065
  (0, vue.watch)(addMenuOpen, (open) => {
5021
5066
  if (open) document.addEventListener("mousedown", closeAddMenuOnOutsideClick);
@@ -5588,8 +5633,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5588
5633
  openDay.value = viewing.value ? dayOfItem(viewing.value) : null;
5589
5634
  });
5590
5635
  return (_ctx, _cache) => {
5591
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$6, [
5592
- !__props.hideHeader ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("header", _hoisted_2$5, [
5636
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$7, [
5637
+ !__props.hideHeader ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("header", _hoisted_2$6, [
5593
5638
  !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5594
5639
  key: 0,
5595
5640
  type: "button",
@@ -5598,8 +5643,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5598
5643
  "aria-label": (0, vue.unref)(t)("collectionsView.backToIndex"),
5599
5644
  "data-testid": "collections-back",
5600
5645
  onClick: goBack
5601
- }, [..._cache[28] || (_cache[28] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : (0, vue.createCommentVNode)("", true),
5602
- collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$5, [(0, vue.createElementVNode)("span", _hoisted_5$5, (0, vue.toDisplayString)(collection.value.icon), 1)])) : (0, vue.createCommentVNode)("", true),
5646
+ }, [..._cache[28] || (_cache[28] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$6)) : (0, vue.createCommentVNode)("", true),
5647
+ collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$6, [(0, vue.createElementVNode)("span", _hoisted_5$5, (0, vue.toDisplayString)(collection.value.icon), 1)])) : (0, vue.createCommentVNode)("", true),
5603
5648
  (0, vue.createElementVNode)("div", _hoisted_6$4, [(0, vue.createElementVNode)("h1", _hoisted_7$4, (0, vue.toDisplayString)(collection.value?.title ?? (0, vue.unref)(t)("collectionsView.title")), 1), collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$4, [(0, vue.createTextVNode)((0, vue.toDisplayString)(collection.value.slug) + " ", 1), isReadOnly.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createElementVNode)("span", _hoisted_9$4, [_cache[29] || (_cache[29] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "lock", -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.readonlyChip")), 1)]), dataSourceRoute.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5604
5649
  key: 0,
5605
5650
  href: dataSourceRoute.value ?? void 0,
@@ -6216,7 +6261,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6216
6261
  });
6217
6262
  //#endregion
6218
6263
  //#region src/vue/chat/View.vue?vue&type=script&setup=true&lang.ts
6219
- var _hoisted_1$5 = {
6264
+ var _hoisted_1$6 = {
6220
6265
  class: "w-full h-full",
6221
6266
  "data-testid": "present-collection"
6222
6267
  };
@@ -6268,7 +6313,7 @@ var View_default = /* @__PURE__ */ (0, vue.defineComponent)({
6268
6313
  });
6269
6314
  }
6270
6315
  return (_ctx, _cache) => {
6271
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$5, [slug.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionView_default, {
6316
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$6, [slug.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionView_default, {
6272
6317
  key: 0,
6273
6318
  slug: slug.value,
6274
6319
  selected: selected.value,
@@ -6291,10 +6336,10 @@ var View_default = /* @__PURE__ */ (0, vue.defineComponent)({
6291
6336
  });
6292
6337
  //#endregion
6293
6338
  //#region src/vue/chat/Preview.vue?vue&type=script&setup=true&lang.ts
6294
- var _hoisted_1$4 = { class: "w-full h-full flex flex-col items-center justify-center p-4 bg-gradient-to-br from-indigo-50 to-slate-50 rounded-lg border-2 border-gray-200" };
6295
- var _hoisted_2$4 = { class: "text-center" };
6296
- var _hoisted_3$4 = { class: "text-gray-900 font-bold text-lg mb-1 line-clamp-2" };
6297
- var _hoisted_4$4 = {
6339
+ var _hoisted_1$5 = { class: "w-full h-full flex flex-col items-center justify-center p-4 bg-gradient-to-br from-indigo-50 to-slate-50 rounded-lg border-2 border-gray-200" };
6340
+ var _hoisted_2$5 = { class: "text-center" };
6341
+ var _hoisted_3$5 = { class: "text-gray-900 font-bold text-lg mb-1 line-clamp-2" };
6342
+ var _hoisted_4$5 = {
6298
6343
  key: 0,
6299
6344
  class: "text-gray-600 text-sm"
6300
6345
  };
@@ -6314,26 +6359,26 @@ var Preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
6314
6359
  const collectionSlug = (0, vue.computed)(() => data.value?.collectionSlug ?? "");
6315
6360
  const itemId = (0, vue.computed)(() => data.value?.itemId);
6316
6361
  return (_ctx, _cache) => {
6317
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$4, [(0, vue.createElementVNode)("div", _hoisted_2$4, [
6362
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$5, [(0, vue.createElementVNode)("div", _hoisted_2$5, [
6318
6363
  _cache[0] || (_cache[0] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-indigo-600 mb-2" }, "collections_bookmark", -1)),
6319
- (0, vue.createElementVNode)("h3", _hoisted_3$4, (0, vue.toDisplayString)(collectionSlug.value || (0, vue.unref)(t)("pluginPresentCollection.fallbackTitle")), 1),
6320
- itemId.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_4$4, (0, vue.toDisplayString)((0, vue.unref)(t)("pluginPresentCollection.itemLabel", { id: itemId.value })), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_5$4, (0, vue.toDisplayString)((0, vue.unref)(t)("pluginPresentCollection.listLabel")), 1))
6364
+ (0, vue.createElementVNode)("h3", _hoisted_3$5, (0, vue.toDisplayString)(collectionSlug.value || (0, vue.unref)(t)("pluginPresentCollection.fallbackTitle")), 1),
6365
+ itemId.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_4$5, (0, vue.toDisplayString)((0, vue.unref)(t)("pluginPresentCollection.itemLabel", { id: itemId.value })), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_5$4, (0, vue.toDisplayString)((0, vue.unref)(t)("pluginPresentCollection.listLabel")), 1))
6321
6366
  ])]);
6322
6367
  };
6323
6368
  }
6324
6369
  });
6325
6370
  //#endregion
6326
6371
  //#region src/vue/components/DiscoverPanel.vue?vue&type=script&setup=true&lang.ts
6327
- var _hoisted_1$3 = { "data-testid": "discover-panel" };
6328
- var _hoisted_2$3 = {
6372
+ var _hoisted_1$4 = { "data-testid": "discover-panel" };
6373
+ var _hoisted_2$4 = {
6329
6374
  key: 0,
6330
6375
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
6331
6376
  };
6332
- var _hoisted_3$3 = {
6377
+ var _hoisted_3$4 = {
6333
6378
  key: 1,
6334
6379
  class: "rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3"
6335
6380
  };
6336
- var _hoisted_4$3 = {
6381
+ var _hoisted_4$4 = {
6337
6382
  key: 2,
6338
6383
  class: "rounded-xl border border-slate-200 bg-white px-6 py-12 text-center text-sm text-slate-500 shadow-sm"
6339
6384
  };
@@ -6443,7 +6488,7 @@ var DiscoverPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
6443
6488
  }
6444
6489
  (0, vue.onMounted)(load);
6445
6490
  return (_ctx, _cache) => {
6446
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$3, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$3, [_cache[0] || (_cache[0] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-teal-600/20 border-t-teal-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$3, [_cache[1] || (_cache[1] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.loadFailed")) + ": " + (0, vue.toDisplayString)(loadError.value), 1)])) : entries.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$3, [_cache[2] || (_cache[2] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "travel_explore", -1)), (0, vue.createElementVNode)("p", _hoisted_5$3, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.empty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_6$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(entries.value, (entry) => {
6491
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$4, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$4, [_cache[0] || (_cache[0] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-teal-600/20 border-t-teal-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$4, [_cache[1] || (_cache[1] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.loadFailed")) + ": " + (0, vue.toDisplayString)(loadError.value), 1)])) : entries.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$4, [_cache[2] || (_cache[2] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "travel_explore", -1)), (0, vue.createElementVNode)("p", _hoisted_5$3, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.empty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_6$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(entries.value, (entry) => {
6447
6492
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
6448
6493
  key: entryKey(entry),
6449
6494
  class: "relative rounded-xl border border-slate-200 bg-white p-5 shadow-sm flex flex-col gap-3",
@@ -6490,6 +6535,164 @@ var DiscoverPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
6490
6535
  }
6491
6536
  });
6492
6537
  //#endregion
6538
+ //#region src/vue/components/CollectionOntologyGraphView.vue?vue&type=script&setup=true&lang.ts
6539
+ var _hoisted_1$3 = {
6540
+ class: "rounded-xl border border-slate-200 bg-white shadow-sm overflow-hidden",
6541
+ "data-testid": "collections-map-panel"
6542
+ };
6543
+ var _hoisted_2$3 = {
6544
+ key: 0,
6545
+ class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
6546
+ };
6547
+ var _hoisted_3$3 = {
6548
+ key: 1,
6549
+ class: "flex items-center gap-3 p-4 text-sm text-red-800"
6550
+ };
6551
+ var _hoisted_4$3 = {
6552
+ key: 2,
6553
+ class: "px-6 py-12 text-center text-sm text-slate-500",
6554
+ "data-testid": "collections-map-empty"
6555
+ };
6556
+ //#endregion
6557
+ //#region src/vue/components/CollectionOntologyGraphView.vue
6558
+ var CollectionOntologyGraphView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6559
+ __name: "CollectionOntologyGraphView",
6560
+ emits: ["open"],
6561
+ setup(__props, { emit: __emit }) {
6562
+ const emit = __emit;
6563
+ const { t } = useCollectionI18n();
6564
+ const cui = collectionUi();
6565
+ const container = (0, vue.ref)(null);
6566
+ const loading = (0, vue.ref)(true);
6567
+ const loadError = (0, vue.ref)(false);
6568
+ const graph = (0, vue.ref)({
6569
+ nodes: [],
6570
+ edges: []
6571
+ });
6572
+ let instance = null;
6573
+ const nodeSize = (node) => node.missing ? 14 : Math.min(40, 20 + Math.round(Math.log2(node.recordCount + 1) * 4));
6574
+ const nodeItem = (node) => ({
6575
+ id: node.slug,
6576
+ name: node.title,
6577
+ symbolSize: nodeSize(node),
6578
+ itemStyle: node.missing ? {
6579
+ color: "#e2e8f0",
6580
+ borderColor: "#94a3b8",
6581
+ borderType: "dashed",
6582
+ borderWidth: 1
6583
+ } : { color: "#4f46e5" },
6584
+ label: node.missing ? { color: "#94a3b8" } : void 0,
6585
+ missing: node.missing === true,
6586
+ recordCount: node.recordCount
6587
+ });
6588
+ const edgeItem = (edge) => ({
6589
+ source: edge.from,
6590
+ target: edge.to,
6591
+ lineStyle: edge.kind === "ref" ? void 0 : { type: "dashed" },
6592
+ label: {
6593
+ show: true,
6594
+ formatter: edge.field,
6595
+ fontSize: 9,
6596
+ color: "#64748b"
6597
+ },
6598
+ field: edge.field,
6599
+ kind: edge.kind,
6600
+ reverseFields: edge.reverseFields
6601
+ });
6602
+ const nodeTooltip = (data) => {
6603
+ if (data.missing) return `<b>${(0, _mulmoclaude_core_wiki.escapeHtml)(data.id)}</b><br>${(0, _mulmoclaude_core_wiki.escapeHtml)(t("collectionsView.mapMissingHint"))}`;
6604
+ return `<b>${(0, _mulmoclaude_core_wiki.escapeHtml)(data.name)}</b><br>${(0, _mulmoclaude_core_wiki.escapeHtml)(data.id)} · ${(0, _mulmoclaude_core_wiki.escapeHtml)(t("collectionsView.mapRecordCount", { count: data.recordCount }))}`;
6605
+ };
6606
+ const edgeTooltip = (data) => {
6607
+ const reverse = data.reverseFields?.length ? ` ⇄ ${data.reverseFields.join(", ")}` : "";
6608
+ return `${(0, _mulmoclaude_core_wiki.escapeHtml)(data.source)} —${(0, _mulmoclaude_core_wiki.escapeHtml)(data.field)}→ ${(0, _mulmoclaude_core_wiki.escapeHtml)(data.target)}<br><span style="color:#64748b">${(0, _mulmoclaude_core_wiki.escapeHtml)(data.kind)}${(0, _mulmoclaude_core_wiki.escapeHtml)(reverse)}</span>`;
6609
+ };
6610
+ const tooltipFormatter = (params) => {
6611
+ const { dataType, data } = params;
6612
+ return dataType === "edge" ? edgeTooltip(data) : nodeTooltip(data);
6613
+ };
6614
+ const buildOption = (value) => ({
6615
+ tooltip: {
6616
+ show: true,
6617
+ formatter: tooltipFormatter
6618
+ },
6619
+ series: [{
6620
+ type: "graph",
6621
+ layout: "force",
6622
+ roam: true,
6623
+ draggable: true,
6624
+ label: {
6625
+ show: true,
6626
+ position: "right",
6627
+ fontSize: 11
6628
+ },
6629
+ force: {
6630
+ repulsion: 180,
6631
+ edgeLength: 120,
6632
+ gravity: .08
6633
+ },
6634
+ emphasis: { focus: "adjacency" },
6635
+ lineStyle: {
6636
+ color: "#cbd5e1",
6637
+ width: 1.5,
6638
+ curveness: .1
6639
+ },
6640
+ edgeSymbol: ["none", "arrow"],
6641
+ edgeSymbolSize: 7,
6642
+ data: value.nodes.map(nodeItem),
6643
+ links: value.edges.map(edgeItem)
6644
+ }]
6645
+ });
6646
+ const render = () => {
6647
+ const element = container.value;
6648
+ if (!element) return;
6649
+ if (!instance) {
6650
+ instance = echarts.init(element);
6651
+ instance.on("click", (params) => {
6652
+ if (params.dataType !== "node") return;
6653
+ const data = params.data;
6654
+ if (typeof data?.id === "string" && data.missing !== true) emit("open", data.id);
6655
+ });
6656
+ }
6657
+ instance.setOption(buildOption(graph.value), true);
6658
+ };
6659
+ const load = async () => {
6660
+ loading.value = true;
6661
+ loadError.value = false;
6662
+ const result = await cui.fetchOntology?.();
6663
+ loading.value = false;
6664
+ if (!result?.ok) {
6665
+ loadError.value = true;
6666
+ return;
6667
+ }
6668
+ graph.value = (0, _mulmoclaude_core_collection.buildOntologyGraph)(result.data.entries);
6669
+ await (0, vue.nextTick)();
6670
+ render();
6671
+ };
6672
+ const handleResize = () => {
6673
+ instance?.resize();
6674
+ };
6675
+ (0, vue.onMounted)(() => {
6676
+ load();
6677
+ window.addEventListener("resize", handleResize);
6678
+ });
6679
+ (0, vue.onBeforeUnmount)(() => {
6680
+ window.removeEventListener("resize", handleResize);
6681
+ instance?.dispose();
6682
+ instance = null;
6683
+ });
6684
+ return (_ctx, _cache) => {
6685
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$3, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$3, [_cache[0] || (_cache[0] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$3, [_cache[1] || (_cache[1] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.loadFailed")), 1)])) : graph.value.nodes.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$3, [_cache[2] || (_cache[2] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "hub", -1)), (0, vue.createElementVNode)("p", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.mapEmpty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
6686
+ key: 3,
6687
+ ref_key: "container",
6688
+ ref: container,
6689
+ class: "w-full h-[32rem]",
6690
+ "data-testid": "collections-map-canvas"
6691
+ }, null, 512))]);
6692
+ };
6693
+ }
6694
+ });
6695
+ //#endregion
6493
6696
  //#region src/vue/starters.ts
6494
6697
  var COLLECTION_STARTERS = [
6495
6698
  {
@@ -6752,6 +6955,7 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6752
6955
  const cui = collectionUi();
6753
6956
  const { pinToggle, reconcileShortcuts } = cui;
6754
6957
  const tab = (0, vue.ref)("installed");
6958
+ const hasOntology = cui.fetchOntology !== void 0;
6755
6959
  const showNewCollectionModal = (0, vue.ref)(false);
6756
6960
  const collections = (0, vue.ref)([]);
6757
6961
  const loading = (0, vue.ref)(true);
@@ -6806,31 +7010,44 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6806
7010
  (0, vue.onMounted)(loadCollections);
6807
7011
  return (_ctx, _cache) => {
6808
7012
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$1, [(0, vue.createElementVNode)("div", _hoisted_2$1, [
6809
- (0, vue.createElementVNode)("div", _hoisted_3$1, [(0, vue.createElementVNode)("div", _hoisted_4$1, [(0, vue.createElementVNode)("h1", _hoisted_5$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.title")), 1), (0, vue.createElementVNode)("div", _hoisted_6$1, [(0, vue.createElementVNode)("button", {
6810
- type: "button",
6811
- class: (0, vue.normalizeClass)(["px-3 h-7 rounded-md text-xs font-semibold transition-colors", tab.value === "installed" ? "bg-white text-indigo-700 shadow-sm" : "text-slate-500 hover:text-slate-700"]),
6812
- "data-testid": "collections-tab-installed",
6813
- onClick: _cache[0] || (_cache[0] = ($event) => tab.value = "installed")
6814
- }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.installedTab")), 3), (0, vue.createElementVNode)("button", {
6815
- type: "button",
6816
- class: (0, vue.normalizeClass)(["px-3 h-7 rounded-md text-xs font-semibold transition-colors", tab.value === "discover" ? "bg-white text-teal-700 shadow-sm" : "text-slate-500 hover:text-slate-700"]),
6817
- "data-testid": "collections-tab-discover",
6818
- onClick: _cache[1] || (_cache[1] = ($event) => tab.value = "discover")
6819
- }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.tab")), 3)])]), tab.value === "installed" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
7013
+ (0, vue.createElementVNode)("div", _hoisted_3$1, [(0, vue.createElementVNode)("div", _hoisted_4$1, [(0, vue.createElementVNode)("h1", _hoisted_5$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.title")), 1), (0, vue.createElementVNode)("div", _hoisted_6$1, [
7014
+ (0, vue.createElementVNode)("button", {
7015
+ type: "button",
7016
+ class: (0, vue.normalizeClass)(["px-3 h-7 rounded-md text-xs font-semibold transition-colors", tab.value === "installed" ? "bg-white text-indigo-700 shadow-sm" : "text-slate-500 hover:text-slate-700"]),
7017
+ "data-testid": "collections-tab-installed",
7018
+ onClick: _cache[0] || (_cache[0] = ($event) => tab.value = "installed")
7019
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.installedTab")), 3),
7020
+ (0, vue.createElementVNode)("button", {
7021
+ type: "button",
7022
+ class: (0, vue.normalizeClass)(["px-3 h-7 rounded-md text-xs font-semibold transition-colors", tab.value === "discover" ? "bg-white text-teal-700 shadow-sm" : "text-slate-500 hover:text-slate-700"]),
7023
+ "data-testid": "collections-tab-discover",
7024
+ onClick: _cache[1] || (_cache[1] = ($event) => tab.value = "discover")
7025
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.tab")), 3),
7026
+ hasOntology ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
7027
+ key: 0,
7028
+ type: "button",
7029
+ class: (0, vue.normalizeClass)(["px-3 h-7 rounded-md text-xs font-semibold transition-colors", tab.value === "map" ? "bg-white text-indigo-700 shadow-sm" : "text-slate-500 hover:text-slate-700"]),
7030
+ "data-testid": "collections-tab-map",
7031
+ onClick: _cache[2] || (_cache[2] = ($event) => tab.value = "map")
7032
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.mapTab")), 3)) : (0, vue.createCommentVNode)("", true)
7033
+ ])]), tab.value === "installed" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
6820
7034
  key: 0,
6821
7035
  type: "button",
6822
7036
  class: "h-8 px-2.5 flex items-center gap-1 rounded bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs transition-colors shadow-sm",
6823
7037
  "data-testid": "collections-add-collection",
6824
- onClick: _cache[2] || (_cache[2] = ($event) => showNewCollectionModal.value = true)
6825
- }, [_cache[4] || (_cache[4] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addCollectionLabel")), 1)])) : (0, vue.createCommentVNode)("", true)]),
7038
+ onClick: _cache[3] || (_cache[3] = ($event) => showNewCollectionModal.value = true)
7039
+ }, [_cache[5] || (_cache[5] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addCollectionLabel")), 1)])) : (0, vue.createCommentVNode)("", true)]),
6826
7040
  showNewCollectionModal.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(NewCollectionModal_default, {
6827
7041
  key: 0,
6828
- onClose: _cache[3] || (_cache[3] = ($event) => showNewCollectionModal.value = false)
7042
+ onClose: _cache[4] || (_cache[4] = ($event) => showNewCollectionModal.value = false)
6829
7043
  })) : (0, vue.createCommentVNode)("", true),
6830
7044
  tab.value === "discover" ? ((0, vue.openBlock)(), (0, vue.createBlock)(DiscoverPanel_default, {
6831
7045
  key: 1,
6832
7046
  onImported: loadCollections
6833
- })) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_7$1, [_cache[5] || (_cache[5] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_8$1, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.loadFailed")) + ": " + (0, vue.toDisplayString)(loadError.value), 1)])) : collections.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9$1, [_cache[7] || (_cache[7] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("p", _hoisted_10$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.indexEmpty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_11$1, [hasReadonlyCollections.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_12$1, [((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(FILTER_CHIPS, (chip) => {
7047
+ })) : tab.value === "map" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionOntologyGraphView_default, {
7048
+ key: 2,
7049
+ onOpen: openCollection
7050
+ })) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 3 }, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_7$1, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_8$1, [_cache[7] || (_cache[7] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.loadFailed")) + ": " + (0, vue.toDisplayString)(loadError.value), 1)])) : collections.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9$1, [_cache[8] || (_cache[8] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("p", _hoisted_10$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.indexEmpty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_11$1, [hasReadonlyCollections.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_12$1, [((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(FILTER_CHIPS, (chip) => {
6834
7051
  return (0, vue.createElementVNode)("button", {
6835
7052
  key: chip,
6836
7053
  type: "button",
@@ -6859,7 +7076,7 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6859
7076
  key: 0,
6860
7077
  class: "inline-flex items-center gap-0.5 px-1.5 py-px rounded bg-amber-50 text-amber-700 border border-amber-200 normal-case tracking-normal",
6861
7078
  "data-testid": `collections-readonly-badge-${collection.slug}`
6862
- }, [_cache[8] || (_cache[8] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "lock", -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.readonlyChip")), 1)], 8, _hoisted_21$1)) : (0, vue.createCommentVNode)("", true)
7079
+ }, [_cache[9] || (_cache[9] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "lock", -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.readonlyChip")), 1)], 8, _hoisted_21$1)) : (0, vue.createCommentVNode)("", true)
6863
7080
  ])]),
6864
7081
  ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(pinToggle)), {
6865
7082
  kind: "collection",
@@ -6879,8 +7096,8 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6879
7096
  "aria-label": (0, vue.unref)(t)("collectionsView.contribute"),
6880
7097
  "data-testid": `collections-contribute-${collection.slug}`,
6881
7098
  onClick: (0, vue.withModifiers)(($event) => startContributeChat(collection), ["stop"])
6882
- }, [..._cache[9] || (_cache[9] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "ios_share", -1)])], 8, _hoisted_22$1)) : (0, vue.createCommentVNode)("", true),
6883
- _cache[10] || (_cache[10] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 flex items-center justify-center rounded-lg bg-slate-50 group-hover:bg-indigo-50 text-slate-400 group-hover:text-indigo-600 transition-all duration-300" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg transition-transform duration-300 group-hover:translate-x-0.5" }, "chevron_right")], -1))
7099
+ }, [..._cache[10] || (_cache[10] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "ios_share", -1)])], 8, _hoisted_22$1)) : (0, vue.createCommentVNode)("", true),
7100
+ _cache[11] || (_cache[11] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 flex items-center justify-center rounded-lg bg-slate-50 group-hover:bg-indigo-50 text-slate-400 group-hover:text-indigo-600 transition-all duration-300" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg transition-transform duration-300 group-hover:translate-x-0.5" }, "chevron_right")], -1))
6884
7101
  ], 40, _hoisted_15$1);
6885
7102
  }), 128))])]))], 64))
6886
7103
  ])]);