@mulmoclaude/collection-plugin 0.5.2 → 0.5.6
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/core/schema.d.ts +24 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.js +2 -2
- package/dist/{schema-LrmrgW12.cjs → schema-5P5ZJPrY.cjs} +11 -1
- package/dist/schema-5P5ZJPrY.cjs.map +1 -0
- package/dist/{schema-DyfSfVzh.js → schema-BcnitlL8.js} +6 -2
- package/dist/schema-BcnitlL8.js.map +1 -0
- package/dist/server/discovery.d.ts +14 -2
- package/dist/server/discovery.d.ts.map +1 -1
- package/dist/server/host.d.ts +25 -0
- package/dist/server/host.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/io.d.ts +6 -0
- package/dist/server/io.d.ts.map +1 -1
- package/dist/server/spawn.d.ts +8 -1
- package/dist/server/spawn.d.ts.map +1 -1
- package/dist/server.cjs +117 -17
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +115 -18
- package/dist/server.js.map +1 -1
- package/dist/style.css +3 -3
- package/dist/vue/components/CollectionCustomView.vue.d.ts +19 -1
- package/dist/vue/components/CollectionCustomView.vue.d.ts.map +1 -1
- package/dist/vue/components/CollectionRecordPanel.vue.d.ts +2 -2
- package/dist/vue/components/CollectionView.vue.d.ts.map +1 -1
- package/dist/vue/uiContext.d.ts +12 -0
- package/dist/vue/uiContext.d.ts.map +1 -1
- package/dist/vue.cjs +144 -4
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +145 -5
- package/dist/vue.js.map +1 -1
- package/package.json +2 -2
- package/dist/schema-DyfSfVzh.js.map +0 -1
- package/dist/schema-LrmrgW12.cjs.map +0 -1
package/dist/vue.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A as buildUpdatedRecord, C as dateSortValue, D as numericSortValue, E as nextSortDirection, F as rowFromItem, G as TOOL_DEFINITION, I as actionVisible, L as fieldVisible, M as draftToRecord, N as emptyRow, O as sortItems, P as firstMissingRequiredField, T as isSortableField, W as resolveEnumColor, _ as ymdKey, a as assignLanes, b as labelFieldFor, i as MINUTES_PER_DAY, j as coerceInlineValue, k as stringSortValue, l as dateOf, n as shortHexId, o as bucketRecords, q as executePresentCollection, r as errorMessage, s as buildMonthGrid, t as defangForPrompt, u as daySlice, v as itemIdOf, w as enumSortValue, x as boolSortValue, y as itemLabelOf } from "./promptSafety-DIQ2yDca.js";
|
|
2
2
|
import { t as deriveAll } from "./deriveAll-BHcs1erT.js";
|
|
3
|
-
import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, effectScope, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useModel, vModelCheckbox, vModelDynamic, vModelSelect, vModelText, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
3
|
+
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";
|
|
4
4
|
import { createI18n } from "vue-i18n";
|
|
5
5
|
import draggable from "vuedraggable";
|
|
6
6
|
//#region src/vue/uiContext.ts
|
|
@@ -2376,12 +2376,15 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /* @__PUR
|
|
|
2376
2376
|
slug: {},
|
|
2377
2377
|
view: {}
|
|
2378
2378
|
},
|
|
2379
|
-
|
|
2379
|
+
emits: ["openItem", "startChat"],
|
|
2380
|
+
setup(__props, { emit: __emit }) {
|
|
2380
2381
|
const { t } = useCollectionI18n();
|
|
2381
2382
|
const props = __props;
|
|
2383
|
+
const emit = __emit;
|
|
2382
2384
|
const loading = ref(true);
|
|
2383
2385
|
const error = ref(null);
|
|
2384
2386
|
const srcdoc = ref(null);
|
|
2387
|
+
const iframeEl = ref(null);
|
|
2385
2388
|
let refreshTimer;
|
|
2386
2389
|
function clearRefresh() {
|
|
2387
2390
|
if (refreshTimer !== void 0) {
|
|
@@ -2430,9 +2433,53 @@ var CollectionCustomView_vue_vue_type_script_setup_true_lang_default = /* @__PUR
|
|
|
2430
2433
|
}
|
|
2431
2434
|
}
|
|
2432
2435
|
watch([() => props.slug, () => props.view.id], () => void load(), { immediate: true });
|
|
2433
|
-
|
|
2436
|
+
let changeUnsub = null;
|
|
2437
|
+
function relayChange() {
|
|
2438
|
+
iframeEl.value?.contentWindow?.postMessage({
|
|
2439
|
+
type: "mc-collection-changed",
|
|
2440
|
+
slug: props.slug
|
|
2441
|
+
}, "*");
|
|
2442
|
+
}
|
|
2443
|
+
watch(() => props.slug, (slug) => {
|
|
2444
|
+
changeUnsub?.();
|
|
2445
|
+
changeUnsub = null;
|
|
2446
|
+
const subscribe = collectionUi().subscribeChanges;
|
|
2447
|
+
if (slug && subscribe) changeUnsub = subscribe(slug, relayChange);
|
|
2448
|
+
}, { immediate: true });
|
|
2449
|
+
function handleOpenItem(body) {
|
|
2450
|
+
const itemId = typeof body.id === "string" ? body.id : String(body.id ?? "");
|
|
2451
|
+
if (!itemId) return;
|
|
2452
|
+
emit("openItem", {
|
|
2453
|
+
id: itemId,
|
|
2454
|
+
mode: body.mode === "edit" ? "edit" : "view"
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
function handleStartChat(body) {
|
|
2458
|
+
const prompt = typeof body.prompt === "string" ? body.prompt.trim() : "";
|
|
2459
|
+
if (!prompt) return;
|
|
2460
|
+
emit("startChat", {
|
|
2461
|
+
prompt,
|
|
2462
|
+
role: typeof body.role === "string" ? body.role : void 0
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2465
|
+
function onWindowMessage(event) {
|
|
2466
|
+
if (event.source !== iframeEl.value?.contentWindow) return;
|
|
2467
|
+
const msg = event.data;
|
|
2468
|
+
if (!msg || msg.slug !== props.slug) return;
|
|
2469
|
+
if (msg.type === "mc-open-item") handleOpenItem(msg);
|
|
2470
|
+
else if (msg.type === "mc-start-chat") handleStartChat(msg);
|
|
2471
|
+
}
|
|
2472
|
+
onMounted(() => window.addEventListener("message", onWindowMessage));
|
|
2473
|
+
onBeforeUnmount(() => {
|
|
2474
|
+
clearRefresh();
|
|
2475
|
+
changeUnsub?.();
|
|
2476
|
+
changeUnsub = null;
|
|
2477
|
+
window.removeEventListener("message", onWindowMessage);
|
|
2478
|
+
});
|
|
2434
2479
|
return (_ctx, _cache) => {
|
|
2435
2480
|
return openBlock(), createElementBlock("div", _hoisted_1$5, [error.value ? (openBlock(), createElementBlock("div", _hoisted_2$4, toDisplayString(unref(t)("collectionsView.customViewError", { error: error.value })), 1)) : loading.value ? (openBlock(), createElementBlock("div", _hoisted_3$4, toDisplayString(unref(t)("collectionsView.customViewLoading")), 1)) : srcdoc.value ? (openBlock(), createElementBlock("iframe", {
|
|
2481
|
+
ref_key: "iframeEl",
|
|
2482
|
+
ref: iframeEl,
|
|
2436
2483
|
key: __props.view.id,
|
|
2437
2484
|
"data-testid": "collection-custom-view-iframe",
|
|
2438
2485
|
title: __props.view.label,
|
|
@@ -2452,7 +2499,7 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
|
2452
2499
|
};
|
|
2453
2500
|
//#endregion
|
|
2454
2501
|
//#region src/vue/components/CollectionCustomView.vue
|
|
2455
|
-
var CollectionCustomView_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CollectionCustomView_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
2502
|
+
var CollectionCustomView_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CollectionCustomView_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-d5fb7ca6"]]);
|
|
2456
2503
|
//#endregion
|
|
2457
2504
|
//#region src/vue/useCollectionRendering.ts
|
|
2458
2505
|
function useCollectionRendering(collection, locale) {
|
|
@@ -2982,6 +3029,17 @@ var _hoisted_83 = { class: "px-6 py-5" };
|
|
|
2982
3029
|
var _hoisted_84 = ["placeholder", "onKeydown"];
|
|
2983
3030
|
var _hoisted_85 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
|
|
2984
3031
|
var _hoisted_86 = ["disabled"];
|
|
3032
|
+
/** `slug` / `selected` are supplied only in EMBEDDED mode (the
|
|
3033
|
+
* `presentCollection` chat card mounts this component and drives both
|
|
3034
|
+
* from the tool result). In standalone route mode (the
|
|
3035
|
+
* `/collections/:slug` page) both are undefined and the component reads
|
|
3036
|
+
* `route.params.slug` / `route.query.selected` as before.
|
|
3037
|
+
*
|
|
3038
|
+
* `sendTextMessage` is forwarded ONLY by the chat card — its presence
|
|
3039
|
+
* is our "rendered inside a chat" signal. When set, chat-triggering
|
|
3040
|
+
* actions send into the current session instead of spawning a new
|
|
3041
|
+
* chat (see `runAction` / `submitChat`). */
|
|
3042
|
+
var LIVE_REFRESH_DEBOUNCE_MS = 150;
|
|
2985
3043
|
//#endregion
|
|
2986
3044
|
//#region src/vue/components/CollectionView.vue
|
|
2987
3045
|
var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
@@ -3355,6 +3413,26 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3355
3413
|
}
|
|
3356
3414
|
maybeAutoRefreshFeed(slug);
|
|
3357
3415
|
}
|
|
3416
|
+
/** Refresh records + schema IN PLACE for a live (pub/sub-driven) update,
|
|
3417
|
+
* preserving the user's browsing state — unlike `loadCollection`, which is the
|
|
3418
|
+
* route-change path and resets it. Specifically: does NOT null `collection`
|
|
3419
|
+
* (so the layout and an active custom-view iframe don't remount), keeps
|
|
3420
|
+
* `searchQuery` / `openDay` / `sortState`, and shows no loading spinner; the
|
|
3421
|
+
* open detail (`viewing`) is re-resolved against the fresh records by id, so it
|
|
3422
|
+
* follows an edited record and closes only if the record was deleted. A failed
|
|
3423
|
+
* fetch is a no-op (keep the current data) — a transient blip shouldn't blank a
|
|
3424
|
+
* view the user is reading. */
|
|
3425
|
+
async function refreshItemsInPlace(slug) {
|
|
3426
|
+
const result = await cui.fetchCollectionDetail(slug);
|
|
3427
|
+
if (!result.ok || activeSlug.value !== slug) return;
|
|
3428
|
+
collection.value = result.data.collection;
|
|
3429
|
+
items.value = result.data.items;
|
|
3430
|
+
dataIssues.value = result.data.issues ?? [];
|
|
3431
|
+
enumOriginallyEmpty.value = snapshotEmptyEnums(result.data.collection.schema, result.data.items);
|
|
3432
|
+
await render.loadLinkedCollections(result.data.collection.schema, slug);
|
|
3433
|
+
if (activeSlug.value !== slug) return;
|
|
3434
|
+
if (viewing.value) viewing.value = findItemById(String(viewing.value[result.data.collection.schema.primaryKey] ?? "")) ?? null;
|
|
3435
|
+
}
|
|
3358
3436
|
function maybeAutoRefreshFeed(slug) {
|
|
3359
3437
|
if (embedded.value) return;
|
|
3360
3438
|
const current = collection.value;
|
|
@@ -3870,6 +3948,30 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3870
3948
|
showDetail(item);
|
|
3871
3949
|
writeSelectedToUrl(itemId);
|
|
3872
3950
|
}
|
|
3951
|
+
/** A custom (sandboxed) view asked to open a record in the shared modal.
|
|
3952
|
+
* `view` → read-only detail, `edit` → straight into the editor. Ungated: the
|
|
3953
|
+
* capability token governs the view's *code*, not user actions through the
|
|
3954
|
+
* host's own trusted modal (no write happens without an explicit Save). */
|
|
3955
|
+
function onCustomViewOpenItem(payload) {
|
|
3956
|
+
const item = findItemById(payload.id);
|
|
3957
|
+
if (!item) return;
|
|
3958
|
+
if (editing.value) closeEditor();
|
|
3959
|
+
if (payload.mode === "edit") {
|
|
3960
|
+
openEdit(item);
|
|
3961
|
+
return;
|
|
3962
|
+
}
|
|
3963
|
+
showDetail(item);
|
|
3964
|
+
writeSelectedToUrl(payload.id);
|
|
3965
|
+
}
|
|
3966
|
+
/** The custom view called `__MC_VIEW.startChat(prompt, role)` — open a new chat
|
|
3967
|
+
* with the prompt prefilled as an editable draft. The host validates `role`
|
|
3968
|
+
* (falls back to General). The view's code only proposes text; the user
|
|
3969
|
+
* approves / edits / sends, so no capability is required. */
|
|
3970
|
+
function onCustomViewStartChat(payload) {
|
|
3971
|
+
const prompt = payload.prompt.trim();
|
|
3972
|
+
if (!prompt) return;
|
|
3973
|
+
cui.startNewChatDraft(prompt, payload.role);
|
|
3974
|
+
}
|
|
3873
3975
|
/** A calendar day cell was activated → open its popup on a clean slate
|
|
3874
3976
|
* (clear any prior selection so the popup opens timeline-only). */
|
|
3875
3977
|
function onOpenDay(day) {
|
|
@@ -3925,6 +4027,42 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
3925
4027
|
loading.value = false;
|
|
3926
4028
|
}
|
|
3927
4029
|
}, { immediate: true });
|
|
4030
|
+
let changeUnsub = null;
|
|
4031
|
+
let liveRefreshTimer;
|
|
4032
|
+
let pendingRemoteRefresh = false;
|
|
4033
|
+
function clearLiveRefreshTimer() {
|
|
4034
|
+
if (liveRefreshTimer !== void 0) {
|
|
4035
|
+
clearTimeout(liveRefreshTimer);
|
|
4036
|
+
liveRefreshTimer = void 0;
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
function onRemoteChange(slug) {
|
|
4040
|
+
clearLiveRefreshTimer();
|
|
4041
|
+
liveRefreshTimer = setTimeout(() => {
|
|
4042
|
+
liveRefreshTimer = void 0;
|
|
4043
|
+
if (editing.value) {
|
|
4044
|
+
pendingRemoteRefresh = true;
|
|
4045
|
+
return;
|
|
4046
|
+
}
|
|
4047
|
+
if (activeSlug.value === slug) refreshItemsInPlace(slug);
|
|
4048
|
+
}, LIVE_REFRESH_DEBOUNCE_MS);
|
|
4049
|
+
}
|
|
4050
|
+
watch(editing, (current) => {
|
|
4051
|
+
if (current || !pendingRemoteRefresh) return;
|
|
4052
|
+
pendingRemoteRefresh = false;
|
|
4053
|
+
if (activeSlug.value) refreshItemsInPlace(activeSlug.value);
|
|
4054
|
+
});
|
|
4055
|
+
watch(activeSlug, (slug) => {
|
|
4056
|
+
changeUnsub?.();
|
|
4057
|
+
changeUnsub = null;
|
|
4058
|
+
clearLiveRefreshTimer();
|
|
4059
|
+
if (slug && cui.subscribeChanges) changeUnsub = cui.subscribeChanges(slug, () => onRemoteChange(slug));
|
|
4060
|
+
}, { immediate: true });
|
|
4061
|
+
onUnmounted(() => {
|
|
4062
|
+
changeUnsub?.();
|
|
4063
|
+
changeUnsub = null;
|
|
4064
|
+
clearLiveRefreshTimer();
|
|
4065
|
+
});
|
|
3928
4066
|
watch([
|
|
3929
4067
|
activeView,
|
|
3930
4068
|
calendarAnchorField,
|
|
@@ -4249,7 +4387,9 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
|
|
|
4249
4387
|
"notified"
|
|
4250
4388
|
])])])) : activeCustomView.value ? (openBlock(), createElementBlock("div", _hoisted_45, [createVNode(CollectionCustomView_default, {
|
|
4251
4389
|
slug: collection.value.slug,
|
|
4252
|
-
view: activeCustomView.value
|
|
4390
|
+
view: activeCustomView.value,
|
|
4391
|
+
onOpenItem: onCustomViewOpenItem,
|
|
4392
|
+
onStartChat: onCustomViewStartChat
|
|
4253
4393
|
}, null, 8, ["slug", "view"])])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_46, [_cache[41] || (_cache[41] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), createElementVNode("p", _hoisted_47, toDisplayString(unref(t)("collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_48, [
|
|
4254
4394
|
_cache[42] || (_cache[42] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
|
|
4255
4395
|
createElementVNode("p", _hoisted_49, toDisplayString(unref(t)("collectionsView.noMatchingItems")), 1),
|