@mulmoclaude/collection-plugin 0.5.21 → 0.6.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.js CHANGED
@@ -2,6 +2,7 @@ import { MINUTES_PER_DAY, TOOL_DEFINITION, actionVisible, assignLanes, boolSortV
2
2
  import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, effectScope, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onUnmounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useModel, vModelCheckbox, vModelDynamic, vModelSelect, vModelText, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
3
3
  import { createI18n } from "vue-i18n";
4
4
  import draggable from "vuedraggable";
5
+ import { REMOTE_VIEW_MAX_BYTES, handleRemoteViewMessage, pageFromItems } from "@mulmoclaude/core/remote-view";
5
6
  import { createTranslationCache } from "@mulmoclaude/core/translation/client";
6
7
  //#region src/vue/uiContext.ts
7
8
  var current = null;
@@ -1185,18 +1186,18 @@ var CollectionRecordModal_default = /* @__PURE__ */ defineComponent({
1185
1186
  });
1186
1187
  //#endregion
1187
1188
  //#region src/vue/components/CollectionCalendarView.vue?vue&type=script&setup=true&lang.ts
1188
- var _hoisted_1$13 = {
1189
+ var _hoisted_1$14 = {
1189
1190
  class: "flex flex-col gap-3",
1190
1191
  "data-testid": "collection-calendar"
1191
1192
  };
1192
- var _hoisted_2$12 = { class: "flex items-center gap-2" };
1193
- var _hoisted_3$12 = ["aria-label"];
1194
- var _hoisted_4$12 = ["aria-label"];
1195
- var _hoisted_5$11 = {
1193
+ var _hoisted_2$13 = { class: "flex items-center gap-2" };
1194
+ var _hoisted_3$13 = ["aria-label"];
1195
+ var _hoisted_4$13 = ["aria-label"];
1196
+ var _hoisted_5$12 = {
1196
1197
  class: "text-sm font-bold text-slate-800 flex-1",
1197
1198
  "data-testid": "collection-calendar-month"
1198
1199
  };
1199
- var _hoisted_6$10 = { class: "grid grid-cols-7 gap-1 text-[10px] font-bold text-slate-400 uppercase tracking-wider select-none" };
1200
+ var _hoisted_6$11 = { class: "grid grid-cols-7 gap-1 text-[10px] font-bold text-slate-400 uppercase tracking-wider select-none" };
1200
1201
  var _hoisted_7$10 = { class: "grid grid-cols-7 gap-1" };
1201
1202
  var _hoisted_8$10 = [
1202
1203
  "aria-label",
@@ -1326,23 +1327,23 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
1326
1327
  viewMonth.value = now.getMonth() + 1;
1327
1328
  }
1328
1329
  return (_ctx, _cache) => {
1329
- return openBlock(), createElementBlock("div", _hoisted_1$13, [
1330
- createElementVNode("div", _hoisted_2$12, [
1330
+ return openBlock(), createElementBlock("div", _hoisted_1$14, [
1331
+ createElementVNode("div", _hoisted_2$13, [
1331
1332
  createElementVNode("button", {
1332
1333
  type: "button",
1333
1334
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
1334
1335
  "aria-label": unref(t)("collectionsView.calendarPrevMonth"),
1335
1336
  "data-testid": "collection-calendar-prev",
1336
1337
  onClick: _cache[0] || (_cache[0] = ($event) => stepMonth(-1))
1337
- }, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$12),
1338
+ }, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_left", -1)])], 8, _hoisted_3$13),
1338
1339
  createElementVNode("button", {
1339
1340
  type: "button",
1340
1341
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
1341
1342
  "aria-label": unref(t)("collectionsView.calendarNextMonth"),
1342
1343
  "data-testid": "collection-calendar-next",
1343
1344
  onClick: _cache[1] || (_cache[1] = ($event) => stepMonth(1))
1344
- }, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$12),
1345
- createElementVNode("h3", _hoisted_5$11, toDisplayString(monthLabel.value), 1),
1345
+ }, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "chevron_right", -1)])], 8, _hoisted_4$13),
1346
+ createElementVNode("h3", _hoisted_5$12, toDisplayString(monthLabel.value), 1),
1346
1347
  createElementVNode("button", {
1347
1348
  type: "button",
1348
1349
  class: "h-8 px-2.5 flex items-center gap-1 rounded border border-slate-200 bg-white text-slate-600 hover:bg-slate-50 text-xs font-bold transition-colors",
@@ -1350,7 +1351,7 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
1350
1351
  onClick: goToday
1351
1352
  }, toDisplayString(unref(t)("collectionsView.calendarToday")), 1)
1352
1353
  ]),
1353
- createElementVNode("div", _hoisted_6$10, [(openBlock(true), createElementBlock(Fragment, null, renderList(weekdayLabels.value, (label, idx) => {
1354
+ createElementVNode("div", _hoisted_6$11, [(openBlock(true), createElementBlock(Fragment, null, renderList(weekdayLabels.value, (label, idx) => {
1354
1355
  return openBlock(), createElementBlock("div", {
1355
1356
  key: idx,
1356
1357
  class: "px-1 py-1 text-center"
@@ -1391,18 +1392,18 @@ var CollectionCalendarView_default = /* @__PURE__ */ defineComponent({
1391
1392
  });
1392
1393
  //#endregion
1393
1394
  //#region src/vue/components/CollectionDayView.vue?vue&type=script&setup=true&lang.ts
1394
- var _hoisted_1$12 = { class: "flex items-center gap-2 border-b border-slate-200 px-4 py-3" };
1395
- var _hoisted_2$11 = {
1395
+ var _hoisted_1$13 = { class: "flex items-center gap-2 border-b border-slate-200 px-4 py-3" };
1396
+ var _hoisted_2$12 = {
1396
1397
  class: "flex-1 text-sm font-bold text-slate-800",
1397
1398
  "data-testid": "collection-day-view-title"
1398
1399
  };
1399
- var _hoisted_3$11 = ["aria-label"];
1400
- var _hoisted_4$11 = ["aria-label"];
1401
- var _hoisted_5$10 = {
1400
+ var _hoisted_3$12 = ["aria-label"];
1401
+ var _hoisted_4$12 = ["aria-label"];
1402
+ var _hoisted_5$11 = {
1402
1403
  key: 0,
1403
1404
  class: "px-4 py-10 text-center text-sm text-slate-400"
1404
1405
  };
1405
- var _hoisted_6$9 = { class: "absolute -top-2 left-0 w-10 pr-1 text-right text-[10px] tabular-nums text-slate-400" };
1406
+ var _hoisted_6$10 = { class: "absolute -top-2 left-0 w-10 pr-1 text-right text-[10px] tabular-nums text-slate-400" };
1406
1407
  var _hoisted_7$9 = {
1407
1408
  class: "absolute inset-y-0 right-0",
1408
1409
  style: { "left": "2.75rem" }
@@ -1583,8 +1584,8 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
1583
1584
  role: "dialog",
1584
1585
  "aria-modal": "true"
1585
1586
  }, [createElementVNode("div", { class: normalizeClass(["flex min-h-0 flex-col", __props.showDetail ? "w-80 shrink-0 border-r border-slate-200" : "w-full"]) }, [
1586
- createElementVNode("div", _hoisted_1$12, [
1587
- createElementVNode("h3", _hoisted_2$11, toDisplayString(dayLabel.value), 1),
1587
+ createElementVNode("div", _hoisted_1$13, [
1588
+ createElementVNode("h3", _hoisted_2$12, toDisplayString(dayLabel.value), 1),
1588
1589
  __props.canCreate ? (openBlock(), createElementBlock("button", {
1589
1590
  key: 0,
1590
1591
  type: "button",
@@ -1592,16 +1593,16 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
1592
1593
  "aria-label": unref(t)("collectionsView.calendarCreateOn", { date: dayKey.value }),
1593
1594
  "data-testid": "collection-day-view-create",
1594
1595
  onClick: onCreate
1595
- }, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$11)) : createCommentVNode("", true),
1596
+ }, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-lg" }, "add", -1)])], 8, _hoisted_3$12)) : createCommentVNode("", true),
1596
1597
  createElementVNode("button", {
1597
1598
  type: "button",
1598
1599
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-500 hover:bg-slate-100 transition-colors",
1599
1600
  "aria-label": unref(t)("collectionsView.dayViewClose"),
1600
1601
  "data-testid": "collection-day-view-close",
1601
1602
  onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
1602
- }, [..._cache[4] || (_cache[4] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$11)
1603
+ }, [..._cache[4] || (_cache[4] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_4$12)
1603
1604
  ]),
1604
- timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_5$10, toDisplayString(unref(t)("collectionsView.dayViewEmpty")), 1)) : (openBlock(), createElementBlock("div", {
1605
+ timedEntries.value.length === 0 && allDayEntries.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_5$11, toDisplayString(unref(t)("collectionsView.dayViewEmpty")), 1)) : (openBlock(), createElementBlock("div", {
1605
1606
  key: 1,
1606
1607
  ref_key: "scrollEl",
1607
1608
  ref: scrollEl,
@@ -1615,7 +1616,7 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
1615
1616
  key: hour,
1616
1617
  class: "absolute left-0 right-0 border-t border-slate-100",
1617
1618
  style: normalizeStyle({ top: `${(hour - 1) * HOUR_PX}px` })
1618
- }, [createElementVNode("span", _hoisted_6$9, toDisplayString(hourLabel(hour - 1)), 1)], 4);
1619
+ }, [createElementVNode("span", _hoisted_6$10, toDisplayString(hourLabel(hour - 1)), 1)], 4);
1619
1620
  }), 64)), createElementVNode("div", _hoisted_7$9, [(openBlock(true), createElementBlock(Fragment, null, renderList(timedEntries.value, (entry) => {
1620
1621
  return openBlock(), createElementBlock("button", {
1621
1622
  key: entry.id,
@@ -1650,15 +1651,15 @@ var CollectionDayView_default = /* @__PURE__ */ defineComponent({
1650
1651
  });
1651
1652
  //#endregion
1652
1653
  //#region src/vue/components/CollectionKanbanView.vue?vue&type=script&setup=true&lang.ts
1653
- var _hoisted_1$11 = {
1654
+ var _hoisted_1$12 = {
1654
1655
  class: "h-full overflow-x-auto overflow-y-hidden",
1655
1656
  "data-testid": "collection-kanban"
1656
1657
  };
1657
- var _hoisted_2$10 = { class: "flex gap-3 h-full p-1 min-w-max" };
1658
- var _hoisted_3$10 = ["data-testid"];
1659
- var _hoisted_4$10 = { class: "flex items-center justify-between px-3 py-2 border-b border-slate-200" };
1660
- var _hoisted_5$9 = { class: "flex items-center gap-2 min-w-0" };
1661
- var _hoisted_6$8 = ["title"];
1658
+ var _hoisted_2$11 = { class: "flex gap-3 h-full p-1 min-w-max" };
1659
+ var _hoisted_3$11 = ["data-testid"];
1660
+ var _hoisted_4$11 = { class: "flex items-center justify-between px-3 py-2 border-b border-slate-200" };
1661
+ var _hoisted_5$10 = { class: "flex items-center gap-2 min-w-0" };
1662
+ var _hoisted_6$9 = ["title"];
1662
1663
  var _hoisted_7$8 = { class: "text-[11px] text-slate-400 shrink-0" };
1663
1664
  var _hoisted_8$8 = [
1664
1665
  "data-testid",
@@ -1771,15 +1772,15 @@ var CollectionKanbanView_default = /* @__PURE__ */ defineComponent({
1771
1772
  emit("move", itemId(item), next);
1772
1773
  }
1773
1774
  return (_ctx, _cache) => {
1774
- return openBlock(), createElementBlock("div", _hoisted_1$11, [createElementVNode("div", _hoisted_2$10, [(openBlock(true), createElementBlock(Fragment, null, renderList(columns.value, (column) => {
1775
+ return openBlock(), createElementBlock("div", _hoisted_1$12, [createElementVNode("div", _hoisted_2$11, [(openBlock(true), createElementBlock(Fragment, null, renderList(columns.value, (column) => {
1775
1776
  return openBlock(), createElementBlock("div", {
1776
1777
  key: column.value,
1777
1778
  "data-testid": `collection-kanban-column-${column.value || "uncategorized"}`,
1778
1779
  class: "w-72 shrink-0 flex flex-col bg-slate-100 rounded-lg"
1779
- }, [createElementVNode("div", _hoisted_4$10, [createElementVNode("div", _hoisted_5$9, [createElementVNode("span", { class: normalizeClass(["w-2 h-2 rounded-full shrink-0", unref(resolveEnumColor)(__props.schema, __props.groupField, column.value).dot]) }, null, 2), createElementVNode("span", {
1780
+ }, [createElementVNode("div", _hoisted_4$11, [createElementVNode("div", _hoisted_5$10, [createElementVNode("span", { class: normalizeClass(["w-2 h-2 rounded-full shrink-0", unref(resolveEnumColor)(__props.schema, __props.groupField, column.value).dot]) }, null, 2), createElementVNode("span", {
1780
1781
  class: "font-semibold text-xs text-slate-600 truncate",
1781
1782
  title: column.label
1782
- }, toDisplayString(column.label), 9, _hoisted_6$8)]), createElementVNode("span", _hoisted_7$8, toDisplayString(itemsByColumn(column.value).length), 1)]), createVNode(unref(draggable), {
1783
+ }, toDisplayString(column.label), 9, _hoisted_6$9)]), createElementVNode("span", _hoisted_7$8, toDisplayString(itemsByColumn(column.value).length), 1)]), createVNode(unref(draggable), {
1783
1784
  "model-value": itemsByColumn(column.value),
1784
1785
  "item-key": __props.schema.primaryKey,
1785
1786
  group: "collection-kanban-cards",
@@ -1810,7 +1811,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ defineComponent({
1810
1811
  "model-value",
1811
1812
  "item-key",
1812
1813
  "onChange"
1813
- ])], 8, _hoisted_3$10);
1814
+ ])], 8, _hoisted_3$11);
1814
1815
  }), 128))])]);
1815
1816
  };
1816
1817
  }
@@ -1840,16 +1841,16 @@ function activatePathLink(event, path, stop = false) {
1840
1841
  }
1841
1842
  //#endregion
1842
1843
  //#region src/vue/components/CollectionEmbedView.vue?vue&type=script&setup=true&lang.ts
1843
- var _hoisted_1$10 = [
1844
+ var _hoisted_1$11 = [
1844
1845
  "href",
1845
1846
  "tabindex",
1846
1847
  "data-testid"
1847
1848
  ];
1848
- var _hoisted_2$9 = { class: "flex items-center justify-between text-[10px] font-bold text-indigo-600/90 tracking-wider uppercase" };
1849
- var _hoisted_3$9 = { class: "flex items-center gap-1.5" };
1850
- var _hoisted_4$9 = { class: "bg-indigo-100/60 text-indigo-700 px-1.5 py-0.5 rounded font-mono font-medium lowercase" };
1851
- var _hoisted_5$8 = { class: "grid gap-x-4 gap-y-3 grid-cols-2" };
1852
- var _hoisted_6$7 = { class: "text-[10px] font-semibold text-slate-400 uppercase tracking-wide" };
1849
+ var _hoisted_2$10 = { class: "flex items-center justify-between text-[10px] font-bold text-indigo-600/90 tracking-wider uppercase" };
1850
+ var _hoisted_3$10 = { class: "flex items-center gap-1.5" };
1851
+ var _hoisted_4$10 = { class: "bg-indigo-100/60 text-indigo-700 px-1.5 py-0.5 rounded font-mono font-medium lowercase" };
1852
+ var _hoisted_5$9 = { class: "grid gap-x-4 gap-y-3 grid-cols-2" };
1853
+ var _hoisted_6$8 = { class: "text-[10px] font-semibold text-slate-400 uppercase tracking-wide" };
1853
1854
  var _hoisted_7$7 = ["data-testid"];
1854
1855
  var _hoisted_8$7 = {
1855
1856
  key: 0,
@@ -1893,17 +1894,17 @@ var CollectionEmbedView_default = /* @__PURE__ */ defineComponent({
1893
1894
  onKeydown: [_cache[1] || (_cache[1] = withKeys(($event) => unref(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId), ["enter"])), _cache[2] || (_cache[2] = withKeys(($event) => unref(activateRefLink)($event, __props.view.targetSlug, __props.view.recordId), ["space"]))]
1894
1895
  }, [
1895
1896
  _cache[7] || (_cache[7] = 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)),
1896
- createElementVNode("div", _hoisted_2$9, [createElementVNode("div", _hoisted_3$9, [_cache[6] || (_cache[6] = createElementVNode("span", { class: "material-icons text-sm" }, "link", -1)), createElementVNode("span", null, toDisplayString(__props.view.targetSlug), 1)]), createElementVNode("span", _hoisted_4$9, toDisplayString(__props.view.recordId), 1)]),
1897
- createElementVNode("div", _hoisted_5$8, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.view.rows, (row) => {
1897
+ createElementVNode("div", _hoisted_2$10, [createElementVNode("div", _hoisted_3$10, [_cache[6] || (_cache[6] = createElementVNode("span", { class: "material-icons text-sm" }, "link", -1)), createElementVNode("span", null, toDisplayString(__props.view.targetSlug), 1)]), createElementVNode("span", _hoisted_4$10, toDisplayString(__props.view.recordId), 1)]),
1898
+ createElementVNode("div", _hoisted_5$9, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.view.rows, (row) => {
1898
1899
  return openBlock(), createElementBlock("div", {
1899
1900
  key: row.key,
1900
1901
  class: "space-y-0.5"
1901
- }, [createElementVNode("div", _hoisted_6$7, toDisplayString(row.label), 1), createElementVNode("div", {
1902
+ }, [createElementVNode("div", _hoisted_6$8, toDisplayString(row.label), 1), createElementVNode("div", {
1902
1903
  class: "text-xs text-slate-700 font-medium break-words",
1903
1904
  "data-testid": `collections-embed-${__props.fieldKey}-${row.key}`
1904
1905
  }, [row.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [row.value === true ? (openBlock(), createElementBlock("span", _hoisted_8$7, "check_circle")) : (openBlock(), createElementBlock("span", _hoisted_9$7, "—"))], 64)) : row.type === "markdown" ? (openBlock(), createElementBlock("p", _hoisted_10$7, toDisplayString(row.display), 1)) : (openBlock(), createElementBlock("span", _hoisted_11$7, toDisplayString(row.display), 1))], 8, _hoisted_7$7)]);
1905
1906
  }), 128))])
1906
- ], 40, _hoisted_1$10)) : (openBlock(), createElementBlock("div", {
1907
+ ], 40, _hoisted_1$11)) : (openBlock(), createElementBlock("div", {
1907
1908
  key: 1,
1908
1909
  class: "relative rounded-xl border border-red-100 bg-red-50/30 p-4 pl-5 shadow-sm",
1909
1910
  "data-testid": `collections-embed-${__props.fieldKey}`
@@ -1931,12 +1932,12 @@ var CollectionEmbedView_default = /* @__PURE__ */ defineComponent({
1931
1932
  });
1932
1933
  //#endregion
1933
1934
  //#region src/vue/components/CollectionRecordPanel.vue?vue&type=script&setup=true&lang.ts
1934
- var _hoisted_1$9 = { class: "flex items-center gap-2 mb-4" };
1935
- var _hoisted_2$8 = { class: "flex-1 min-w-0" };
1936
- var _hoisted_3$8 = { class: "block text-[9px] font-bold text-slate-400 uppercase tracking-wider" };
1937
- var _hoisted_4$8 = ["data-testid"];
1938
- var _hoisted_5$7 = ["disabled"];
1939
- var _hoisted_6$6 = {
1935
+ var _hoisted_1$10 = { class: "flex items-center gap-2 mb-4" };
1936
+ var _hoisted_2$9 = { class: "flex-1 min-w-0" };
1937
+ var _hoisted_3$9 = { class: "block text-[9px] font-bold text-slate-400 uppercase tracking-wider" };
1938
+ var _hoisted_4$9 = ["data-testid"];
1939
+ var _hoisted_5$8 = ["disabled"];
1940
+ var _hoisted_6$7 = {
1940
1941
  key: 1,
1941
1942
  class: "flex items-center gap-2"
1942
1943
  };
@@ -2300,10 +2301,10 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
2300
2301
  onSubmit: _cache[5] || (_cache[5] = withModifiers(($event) => emit("submit"), ["prevent"]))
2301
2302
  }, {
2302
2303
  default: withCtx(() => [
2303
- createElementVNode("div", _hoisted_1$9, [createElementVNode("div", _hoisted_2$8, [createElementVNode("span", _hoisted_3$8, toDisplayString(__props.collection.title), 1), createElementVNode("h2", {
2304
+ createElementVNode("div", _hoisted_1$10, [createElementVNode("div", _hoisted_2$9, [createElementVNode("span", _hoisted_3$9, toDisplayString(__props.collection.title), 1), createElementVNode("h2", {
2304
2305
  class: "text-base font-bold text-slate-800 truncate",
2305
2306
  "data-testid": editing.value ? "collections-edit-title" : "collections-detail-title"
2306
- }, toDisplayString(headerTitle.value), 9, _hoisted_4$8)]), editing.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("button", {
2307
+ }, toDisplayString(headerTitle.value), 9, _hoisted_4$9)]), editing.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("button", {
2307
2308
  type: "button",
2308
2309
  class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
2309
2310
  "data-testid": "collections-editor-cancel",
@@ -2313,7 +2314,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
2313
2314
  class: "h-8 px-2.5 rounded bg-indigo-600 text-white font-bold text-xs hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-sm shadow-indigo-600/10",
2314
2315
  disabled: __props.saving,
2315
2316
  "data-testid": "collections-editor-save"
2316
- }, toDisplayString(__props.saving ? unref(t)("common.saving") : unref(t)("common.save")), 9, _hoisted_5$7)], 64)) : (openBlock(), createElementBlock("div", _hoisted_6$6, [
2317
+ }, toDisplayString(__props.saving ? unref(t)("common.saving") : unref(t)("common.save")), 9, _hoisted_5$8)], 64)) : (openBlock(), createElementBlock("div", _hoisted_6$7, [
2317
2318
  (openBlock(true), createElementBlock(Fragment, null, renderList(__props.visibleActions, (action) => {
2318
2319
  return openBlock(), createElementBlock("button", {
2319
2320
  key: action.id,
@@ -2594,15 +2595,15 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
2594
2595
  });
2595
2596
  //#endregion
2596
2597
  //#region src/vue/components/CollectionViewConfigModal.vue?vue&type=script&setup=true&lang.ts
2597
- var _hoisted_1$8 = {
2598
+ var _hoisted_1$9 = {
2598
2599
  "data-testid": "collection-config-modal",
2599
2600
  class: "flex flex-col overflow-hidden"
2600
2601
  };
2601
- var _hoisted_2$7 = { class: "flex items-center justify-between gap-2 border-b border-slate-100 px-5 py-3" };
2602
- var _hoisted_3$7 = { class: "text-sm font-bold text-slate-700" };
2603
- var _hoisted_4$7 = ["title", "aria-label"];
2604
- var _hoisted_5$6 = { class: "overflow-y-auto px-5 py-4" };
2605
- var _hoisted_6$5 = { class: "mb-2 text-[10px] font-bold uppercase tracking-wider text-slate-400" };
2602
+ var _hoisted_2$8 = { class: "flex items-center justify-between gap-2 border-b border-slate-100 px-5 py-3" };
2603
+ var _hoisted_3$8 = { class: "text-sm font-bold text-slate-700" };
2604
+ var _hoisted_4$8 = ["title", "aria-label"];
2605
+ var _hoisted_5$7 = { class: "overflow-y-auto px-5 py-4" };
2606
+ var _hoisted_6$6 = { class: "mb-2 text-[10px] font-bold uppercase tracking-wider text-slate-400" };
2606
2607
  var _hoisted_7$5 = {
2607
2608
  key: 0,
2608
2609
  class: "mb-3 rounded border border-rose-200 bg-rose-50 px-3 py-2 text-xs font-medium text-rose-600",
@@ -2666,15 +2667,15 @@ var CollectionViewConfigModal_default = /* @__PURE__ */ defineComponent({
2666
2667
  }
2667
2668
  return (_ctx, _cache) => {
2668
2669
  return openBlock(), createBlock(CollectionRecordModal_default, { onClose: _cache[1] || (_cache[1] = ($event) => emit("close")) }, {
2669
- default: withCtx(() => [createElementVNode("div", _hoisted_1$8, [createElementVNode("header", _hoisted_2$7, [createElementVNode("h2", _hoisted_3$7, toDisplayString(unref(t)("collectionsView.config.title", { title: __props.title })), 1), createElementVNode("button", {
2670
+ default: withCtx(() => [createElementVNode("div", _hoisted_1$9, [createElementVNode("header", _hoisted_2$8, [createElementVNode("h2", _hoisted_3$8, toDisplayString(unref(t)("collectionsView.config.title", { title: __props.title })), 1), createElementVNode("button", {
2670
2671
  type: "button",
2671
2672
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-50 hover:text-slate-600",
2672
2673
  title: unref(t)("common.close"),
2673
2674
  "aria-label": unref(t)("common.close"),
2674
2675
  "data-testid": "collection-config-close",
2675
2676
  onClick: _cache[0] || (_cache[0] = ($event) => emit("close"))
2676
- }, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_4$7)]), createElementVNode("div", _hoisted_5$6, [
2677
- createElementVNode("h3", _hoisted_6$5, toDisplayString(unref(t)("collectionsView.config.viewsHeading")), 1),
2677
+ }, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_4$8)]), createElementVNode("div", _hoisted_5$7, [
2678
+ createElementVNode("h3", _hoisted_6$6, toDisplayString(unref(t)("collectionsView.config.viewsHeading")), 1),
2678
2679
  error.value ? (openBlock(), createElementBlock("p", _hoisted_7$5, toDisplayString(error.value), 1)) : createCommentVNode("", true),
2679
2680
  __props.views.length > 0 ? (openBlock(), createElementBlock("ul", _hoisted_8$5, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.views, (view) => {
2680
2681
  return openBlock(), createElementBlock("li", {
@@ -2702,19 +2703,19 @@ var CollectionViewConfigModal_default = /* @__PURE__ */ defineComponent({
2702
2703
  });
2703
2704
  //#endregion
2704
2705
  //#region src/vue/components/CollectionCustomView.vue?vue&type=script&setup=true&lang.ts
2705
- var _hoisted_1$7 = { class: "custom-view-container" };
2706
- var _hoisted_2$6 = {
2706
+ var _hoisted_1$8 = { class: "custom-view-container" };
2707
+ var _hoisted_2$7 = {
2707
2708
  key: 0,
2708
2709
  class: "custom-view-message",
2709
2710
  role: "alert",
2710
2711
  "data-testid": "collection-custom-view-error"
2711
2712
  };
2712
- var _hoisted_3$6 = {
2713
+ var _hoisted_3$7 = {
2713
2714
  key: 1,
2714
2715
  class: "custom-view-message",
2715
2716
  "data-testid": "collection-custom-view-loading"
2716
2717
  };
2717
- var _hoisted_4$6 = ["title", "srcdoc"];
2718
+ var _hoisted_4$7 = ["title", "srcdoc"];
2718
2719
  var REMINT_LEAD_MS = 6e4;
2719
2720
  var MIN_REMINT_DELAY_MS = 1e4;
2720
2721
  var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
@@ -2836,7 +2837,7 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /*@__PURE
2836
2837
  window.removeEventListener("message", onWindowMessage);
2837
2838
  });
2838
2839
  return (_ctx, _cache) => {
2839
- return openBlock(), createElementBlock("div", _hoisted_1$7, [error.value ? (openBlock(), createElementBlock("div", _hoisted_2$6, toDisplayString(unref(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? (openBlock(), createElementBlock("div", _hoisted_3$6, toDisplayString(unref(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? (openBlock(), createElementBlock("iframe", {
2840
+ return openBlock(), createElementBlock("div", _hoisted_1$8, [error.value ? (openBlock(), createElementBlock("div", _hoisted_2$7, toDisplayString(unref(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? (openBlock(), createElementBlock("div", _hoisted_3$7, toDisplayString(unref(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? (openBlock(), createElementBlock("iframe", {
2840
2841
  ref_key: "iframeEl",
2841
2842
  ref: iframeEl,
2842
2843
  key: __props.view.id,
@@ -2845,7 +2846,7 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /*@__PURE
2845
2846
  srcdoc: srcdoc.value,
2846
2847
  sandbox: "allow-scripts allow-popups allow-popups-to-escape-sandbox",
2847
2848
  class: "w-full h-full border-0"
2848
- }, null, 8, _hoisted_4$6)) : createCommentVNode("", true)]);
2849
+ }, null, 8, _hoisted_4$7)) : createCommentVNode("", true)]);
2849
2850
  };
2850
2851
  }
2851
2852
  });
@@ -2860,6 +2861,110 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
2860
2861
  //#region src/vue/components/CollectionCustomView.vue
2861
2862
  var CollectionCustomView_default = /*#__PURE__*/ _plugin_vue_export_helper_default(CollectionCustomView_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-b22228db"]]);
2862
2863
  //#endregion
2864
+ //#region src/vue/components/CollectionRemoteViewPreview.vue?vue&type=script&setup=true&lang.ts
2865
+ var _hoisted_1$7 = {
2866
+ class: "remote-preview-container",
2867
+ "data-testid": "collection-remote-view-preview"
2868
+ };
2869
+ var _hoisted_2$6 = {
2870
+ key: 0,
2871
+ class: "remote-preview-message",
2872
+ role: "alert",
2873
+ "data-testid": "collection-remote-view-error"
2874
+ };
2875
+ var _hoisted_3$6 = {
2876
+ key: 1,
2877
+ class: "remote-preview-message",
2878
+ "data-testid": "collection-remote-view-loading"
2879
+ };
2880
+ var _hoisted_4$6 = { class: "phone-frame" };
2881
+ var _hoisted_5$6 = ["title", "srcdoc"];
2882
+ var _hoisted_6$5 = {
2883
+ class: "remote-preview-caption",
2884
+ "data-testid": "collection-remote-view-size"
2885
+ };
2886
+ //#endregion
2887
+ //#region src/vue/components/CollectionRemoteViewPreview.vue
2888
+ var CollectionRemoteViewPreview_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
2889
+ __name: "CollectionRemoteViewPreview",
2890
+ props: {
2891
+ slug: {},
2892
+ view: {},
2893
+ primaryKey: {},
2894
+ items: {}
2895
+ },
2896
+ emits: ["startChat"],
2897
+ setup(__props, { emit: __emit }) {
2898
+ const { t } = useCollectionI18n();
2899
+ const props = __props;
2900
+ const emit = __emit;
2901
+ const loading = ref(true);
2902
+ const error = ref(null);
2903
+ const srcdoc = ref(null);
2904
+ const bytes = ref(0);
2905
+ const iframeEl = ref(null);
2906
+ const sizeCaption = computed(() => `${Math.max(1, Math.round(bytes.value / 1024))} KB / ${Math.round(REMOTE_VIEW_MAX_BYTES / 1024)} KB`);
2907
+ let loadSeq = 0;
2908
+ async function load() {
2909
+ const seq = ++loadSeq;
2910
+ const stale = () => seq !== loadSeq;
2911
+ loading.value = true;
2912
+ error.value = null;
2913
+ srcdoc.value = null;
2914
+ const binding = collectionUi();
2915
+ try {
2916
+ const resp = await binding.fetchRemoteView?.(props.slug, props.view.id, binding.localeTag());
2917
+ if (stale()) return;
2918
+ if (!resp) {
2919
+ error.value = "fetchRemoteView is not wired on this host";
2920
+ return;
2921
+ }
2922
+ if (!resp.ok) {
2923
+ error.value = resp.error;
2924
+ return;
2925
+ }
2926
+ bytes.value = resp.data.bytes;
2927
+ srcdoc.value = resp.data.srcdoc;
2928
+ } catch (err) {
2929
+ if (!stale()) error.value = errorMessage(err);
2930
+ } finally {
2931
+ if (!stale()) loading.value = false;
2932
+ }
2933
+ }
2934
+ watch([
2935
+ () => props.slug,
2936
+ () => props.view.id,
2937
+ () => collectionUi().localeTag()
2938
+ ], () => void load(), { immediate: true });
2939
+ function onWindowMessage(event) {
2940
+ const target = event.source;
2941
+ if (!target || target !== iframeEl.value?.contentWindow) return;
2942
+ handleRemoteViewMessage(event.data, {
2943
+ slug: props.slug,
2944
+ getPage: (request) => pageFromItems(props.items, request, props.primaryKey),
2945
+ onStartChat: (prompt, role) => emit("startChat", {
2946
+ prompt,
2947
+ role
2948
+ })
2949
+ }, (message) => target.postMessage(message, "*"));
2950
+ }
2951
+ onMounted(() => window.addEventListener("message", onWindowMessage));
2952
+ onBeforeUnmount(() => window.removeEventListener("message", onWindowMessage));
2953
+ return (_ctx, _cache) => {
2954
+ return openBlock(), createElementBlock("div", _hoisted_1$7, [error.value ? (openBlock(), createElementBlock("div", _hoisted_2$6, toDisplayString(unref(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? (openBlock(), createElementBlock("div", _hoisted_3$6, toDisplayString(unref(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createElementVNode("div", _hoisted_4$6, [(openBlock(), createElementBlock("iframe", {
2955
+ ref_key: "iframeEl",
2956
+ ref: iframeEl,
2957
+ key: __props.view.id,
2958
+ "data-testid": "collection-remote-view-iframe",
2959
+ title: __props.view.label,
2960
+ srcdoc: srcdoc.value,
2961
+ sandbox: "allow-scripts allow-popups allow-popups-to-escape-sandbox",
2962
+ class: "phone-screen"
2963
+ }, null, 8, _hoisted_5$6))]), createElementVNode("div", _hoisted_6$5, toDisplayString(sizeCaption.value), 1)], 64)) : createCommentVNode("", true)]);
2964
+ };
2965
+ }
2966
+ }), [["__scopeId", "data-v-b9e3d51f"]]);
2967
+ //#endregion
2863
2968
  //#region src/vue/useCollectionRendering.ts
2864
2969
  function stepForFieldType(type) {
2865
2970
  if (type === "money") return "0.01";
@@ -3939,8 +4044,13 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
3939
4044
  * vanished (e.g. `view = "kanban"` after switching to an enum-less
3940
4045
  * collection) back to "table". Single source of truth for the toggle and
3941
4046
  * the body branches. */
3942
- /** Custom (LLM-authored) HTML views declared on the schema. */
3943
- const customViews = computed(() => collection.value?.schema.views ?? []);
4047
+ /** Custom (LLM-authored) HTML views declared on the schema. Mobile-target
4048
+ * views need the host's `fetchRemoteView` binding (the phone-frame preview's
4049
+ * data source) — on a host without it they're hidden from the selector. */
4050
+ const customViews = computed(() => {
4051
+ const views = collection.value?.schema.views ?? [];
4052
+ return cui.fetchRemoteView ? views : views.filter((entry) => entry.target !== "mobile");
4053
+ });
3944
4054
  const hasCustomViews = computed(() => customViews.value.length > 0);
3945
4055
  const activeView = computed(() => {
3946
4056
  if (view.value === "calendar" && hasCalendar.value) return "calendar";
@@ -4666,7 +4776,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
4666
4776
  "aria-pressed": activeView.value === unref(customViewKey)(cv.id),
4667
4777
  "data-testid": `collection-view-custom-${cv.id}`,
4668
4778
  onClick: ($event) => setCustomView(cv.id)
4669
- }, [createElementVNode("span", _hoisted_27$1, toDisplayString(cv.icon || "dashboard_customize"), 1), createElementVNode("span", null, toDisplayString(cv.label), 1)], 10, _hoisted_26$1);
4779
+ }, [createElementVNode("span", _hoisted_27$1, toDisplayString(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), createElementVNode("span", null, toDisplayString(cv.label), 1)], 10, _hoisted_26$1);
4670
4780
  }), 128)),
4671
4781
  canAddCustomView.value ? (openBlock(), createElementBlock("button", {
4672
4782
  key: 2,
@@ -4836,12 +4946,25 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
4836
4946
  "group-field",
4837
4947
  "selected",
4838
4948
  "notified"
4839
- ])])])) : activeCustomView.value ? (openBlock(), createElementBlock("div", _hoisted_47, [createVNode(CollectionCustomView_default, {
4949
+ ])])])) : activeCustomView.value ? (openBlock(), createElementBlock("div", _hoisted_47, [activeCustomView.value.target === "mobile" ? (openBlock(), createBlock(CollectionRemoteViewPreview_default, {
4950
+ key: 0,
4951
+ slug: collection.value.slug,
4952
+ view: activeCustomView.value,
4953
+ "primary-key": collection.value.schema.primaryKey,
4954
+ items: items.value,
4955
+ onStartChat: onCustomViewStartChat
4956
+ }, null, 8, [
4957
+ "slug",
4958
+ "view",
4959
+ "primary-key",
4960
+ "items"
4961
+ ])) : (openBlock(), createBlock(CollectionCustomView_default, {
4962
+ key: 1,
4840
4963
  slug: collection.value.slug,
4841
4964
  view: activeCustomView.value,
4842
4965
  onOpenItem: onCustomViewOpenItem,
4843
4966
  onStartChat: onCustomViewStartChat
4844
- }, null, 8, ["slug", "view"])])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_48, [_cache[42] || (_cache[42] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), createElementVNode("p", _hoisted_49, toDisplayString(unref(t)("collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_50, [
4967
+ }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_48, [_cache[42] || (_cache[42] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), createElementVNode("p", _hoisted_49, toDisplayString(unref(t)("collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_50, [
4845
4968
  _cache[43] || (_cache[43] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
4846
4969
  createElementVNode("p", _hoisted_51, toDisplayString(unref(t)("collectionsView.noMatchingItems")), 1),
4847
4970
  createElementVNode("button", {