@mulmoclaude/collection-plugin 0.12.0 → 0.13.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
@@ -114,6 +114,11 @@ var i18n = (0, vue_i18n.createI18n)({
114
114
  searchSummary: "Showing {shown} of {total}",
115
115
  noMatchingItems: "No matching items",
116
116
  clearSearch: "Clear search",
117
+ flagFilterGroup: "Flag filters",
118
+ flagFilterAll: "Filter by {label}",
119
+ flagFilterHide: "Hiding {label}",
120
+ flagFilterOnly: "Only {label}",
121
+ flagDoneChip: "Done",
117
122
  sortBy: "Sort by {field}",
118
123
  openCollection: "Open {title}",
119
124
  createTitle: "Add new",
@@ -257,6 +262,11 @@ var i18n = (0, vue_i18n.createI18n)({
257
262
  searchSummary: "{total} 件中 {shown} 件を表示",
258
263
  noMatchingItems: "一致する項目がありません",
259
264
  clearSearch: "検索をクリア",
265
+ flagFilterGroup: "フラグで絞り込み",
266
+ flagFilterAll: "{label} で絞り込む",
267
+ flagFilterHide: "{label} を非表示中",
268
+ flagFilterOnly: "{label} のみ表示中",
269
+ flagDoneChip: "完了",
260
270
  sortBy: "{field}で並べ替え",
261
271
  openCollection: "{title} を開く",
262
272
  createTitle: "新規追加",
@@ -400,6 +410,11 @@ var i18n = (0, vue_i18n.createI18n)({
400
410
  searchSummary: "显示 {total} 条中的 {shown} 条",
401
411
  noMatchingItems: "没有匹配的项目",
402
412
  clearSearch: "清除搜索",
413
+ flagFilterGroup: "标记筛选",
414
+ flagFilterAll: "按{label}筛选",
415
+ flagFilterHide: "已隐藏{label}",
416
+ flagFilterOnly: "仅显示{label}",
417
+ flagDoneChip: "已完成",
403
418
  sortBy: "按{field}排序",
404
419
  openCollection: "打开 {title}",
405
420
  createTitle: "新增",
@@ -543,6 +558,11 @@ var i18n = (0, vue_i18n.createI18n)({
543
558
  searchSummary: "{total}개 중 {shown}개 표시",
544
559
  noMatchingItems: "일치하는 항목이 없습니다",
545
560
  clearSearch: "검색 지우기",
561
+ flagFilterGroup: "플래그 필터",
562
+ flagFilterAll: "{label}(으)로 필터",
563
+ flagFilterHide: "{label} 숨김",
564
+ flagFilterOnly: "{label}만 표시",
565
+ flagDoneChip: "완료",
546
566
  sortBy: "{field} 기준 정렬",
547
567
  openCollection: "{title} 열기",
548
568
  createTitle: "새로 추가",
@@ -686,6 +706,11 @@ var i18n = (0, vue_i18n.createI18n)({
686
706
  searchSummary: "Mostrando {shown} de {total}",
687
707
  noMatchingItems: "No hay elementos coincidentes",
688
708
  clearSearch: "Borrar búsqueda",
709
+ flagFilterGroup: "Filtros por indicador",
710
+ flagFilterAll: "Filtrar por {label}",
711
+ flagFilterHide: "Ocultando {label}",
712
+ flagFilterOnly: "Solo {label}",
713
+ flagDoneChip: "Hecho",
689
714
  sortBy: "Ordenar por {field}",
690
715
  openCollection: "Abrir {title}",
691
716
  createTitle: "Añadir nuevo",
@@ -829,6 +854,11 @@ var i18n = (0, vue_i18n.createI18n)({
829
854
  searchSummary: "Mostrando {shown} de {total}",
830
855
  noMatchingItems: "Nenhum item correspondente",
831
856
  clearSearch: "Limpar busca",
857
+ flagFilterGroup: "Filtros por marcador",
858
+ flagFilterAll: "Filtrar por {label}",
859
+ flagFilterHide: "Ocultando {label}",
860
+ flagFilterOnly: "Somente {label}",
861
+ flagDoneChip: "Concluído",
832
862
  sortBy: "Ordenar por {field}",
833
863
  openCollection: "Abrir {title}",
834
864
  createTitle: "Adicionar novo",
@@ -972,6 +1002,11 @@ var i18n = (0, vue_i18n.createI18n)({
972
1002
  searchSummary: "Affichage de {shown} sur {total}",
973
1003
  noMatchingItems: "Aucun élément correspondant",
974
1004
  clearSearch: "Effacer la recherche",
1005
+ flagFilterGroup: "Filtres par indicateur",
1006
+ flagFilterAll: "Filtrer par {label}",
1007
+ flagFilterHide: "{label} masqué",
1008
+ flagFilterOnly: "Uniquement {label}",
1009
+ flagDoneChip: "Terminé",
975
1010
  sortBy: "Trier par {field}",
976
1011
  openCollection: "Ouvrir {title}",
977
1012
  createTitle: "Ajouter",
@@ -1115,6 +1150,11 @@ var i18n = (0, vue_i18n.createI18n)({
1115
1150
  searchSummary: "{shown} von {total} werden angezeigt",
1116
1151
  noMatchingItems: "Keine passenden Einträge",
1117
1152
  clearSearch: "Suche zurücksetzen",
1153
+ flagFilterGroup: "Flag-Filter",
1154
+ flagFilterAll: "Nach {label} filtern",
1155
+ flagFilterHide: "{label} ausgeblendet",
1156
+ flagFilterOnly: "Nur {label}",
1157
+ flagDoneChip: "Erledigt",
1118
1158
  sortBy: "Nach {field} sortieren",
1119
1159
  openCollection: "{title} öffnen",
1120
1160
  createTitle: "Neu hinzufügen",
@@ -2595,77 +2635,79 @@ var _hoisted_57$1 = {
2595
2635
  key: 2,
2596
2636
  class: "text-slate-300"
2597
2637
  };
2598
- var _hoisted_58$1 = [
2638
+ var _hoisted_58$1 = ["data-testid"];
2639
+ var _hoisted_59$1 = ["data-testid"];
2640
+ var _hoisted_60$1 = [
2599
2641
  "href",
2600
2642
  "tabindex",
2601
2643
  "data-testid",
2602
2644
  "onClick",
2603
2645
  "onKeydown"
2604
2646
  ];
2605
- var _hoisted_59$1 = {
2606
- key: 3,
2647
+ var _hoisted_61$1 = {
2648
+ key: 4,
2607
2649
  class: "font-semibold text-slate-900 tabular-nums text-sm"
2608
2650
  };
2609
- var _hoisted_60$1 = {
2610
- key: 4,
2651
+ var _hoisted_62$1 = {
2652
+ key: 5,
2611
2653
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-2 py-0.5 rounded border border-indigo-100/50"
2612
2654
  };
2613
- var _hoisted_61$1 = ["data-testid"];
2614
- var _hoisted_62$1 = {
2615
- key: 6,
2655
+ var _hoisted_63$1 = ["data-testid"];
2656
+ var _hoisted_64$1 = {
2657
+ key: 7,
2616
2658
  class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1"
2617
2659
  };
2618
- var _hoisted_63$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2619
- var _hoisted_64$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2620
- var _hoisted_65$1 = { class: "divide-y divide-slate-100" };
2621
- var _hoisted_66$1 = {
2660
+ var _hoisted_65$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2661
+ var _hoisted_66$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2662
+ var _hoisted_67$1 = { class: "divide-y divide-slate-100" };
2663
+ var _hoisted_68$1 = {
2622
2664
  key: 0,
2623
2665
  class: "material-icons text-emerald-600 text-base"
2624
2666
  };
2625
- var _hoisted_67$1 = {
2667
+ var _hoisted_69$1 = {
2626
2668
  key: 1,
2627
2669
  class: "text-slate-300"
2628
2670
  };
2629
- var _hoisted_68$1 = {
2630
- key: 7,
2671
+ var _hoisted_70$1 = {
2672
+ key: 8,
2631
2673
  class: "text-slate-400 italic"
2632
2674
  };
2633
- var _hoisted_69$1 = {
2634
- key: 8,
2675
+ var _hoisted_71$1 = {
2676
+ key: 9,
2635
2677
  class: "bg-slate-50 rounded-xl p-4 border border-slate-200/60 text-slate-600 text-xs whitespace-pre-wrap leading-relaxed max-h-[30vh] overflow-y-auto"
2636
2678
  };
2637
- var _hoisted_70$1 = [
2679
+ var _hoisted_72$1 = [
2638
2680
  "src",
2639
2681
  "alt",
2640
2682
  "data-testid"
2641
2683
  ];
2642
- var _hoisted_71$1 = ["href", "data-testid"];
2643
- var _hoisted_72$1 = ["href", "data-testid"];
2644
- var _hoisted_73$1 = [
2684
+ var _hoisted_73$1 = ["href", "data-testid"];
2685
+ var _hoisted_74$1 = ["href", "data-testid"];
2686
+ var _hoisted_75$1 = [
2645
2687
  "href",
2646
2688
  "data-testid",
2647
2689
  "onClick"
2648
2690
  ];
2649
- var _hoisted_74$1 = {
2650
- key: 15,
2691
+ var _hoisted_76$1 = {
2692
+ key: 16,
2651
2693
  class: "text-slate-800 font-semibold"
2652
2694
  };
2653
- var _hoisted_75$1 = {
2695
+ var _hoisted_77$1 = {
2654
2696
  key: 0,
2655
2697
  class: "col-span-full text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl"
2656
2698
  };
2657
- var _hoisted_76$1 = {
2699
+ var _hoisted_78$1 = {
2658
2700
  key: 1,
2659
2701
  class: "mt-5 pt-4 border-t border-slate-200/60",
2660
2702
  "data-testid": "collections-detail-chat"
2661
2703
  };
2662
- var _hoisted_77$1 = {
2704
+ var _hoisted_79$1 = {
2663
2705
  class: "block text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1.5",
2664
2706
  for: "collections-detail-chat-input"
2665
2707
  };
2666
- var _hoisted_78$1 = { class: "flex items-end gap-2" };
2667
- var _hoisted_79$1 = ["placeholder", "onKeydown"];
2668
- var _hoisted_80$1 = ["disabled"];
2708
+ var _hoisted_80$1 = { class: "flex items-end gap-2" };
2709
+ var _hoisted_81$1 = ["placeholder", "onKeydown"];
2710
+ var _hoisted_82$1 = ["disabled"];
2669
2711
  //#endregion
2670
2712
  //#region src/vue/components/CollectionRecordPanel.vue
2671
2713
  var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -3027,8 +3069,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3027
3069
  key: 3,
3028
3070
  class: "text-xs font-medium text-slate-700 break-words",
3029
3071
  "data-testid": `collections-detail-value-${key}`
3030
- }, [field.type === "toggle" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_53$1, [_cache[12] || (_cache[12] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_54$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1))], 64)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [detailRecord.value[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_55$1, [_cache[13] || (_cache[13] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_56$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_57$1, "—"))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3031
- key: 2,
3072
+ }, [field.type === "toggle" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_53$1, [_cache[12] || (_cache[12] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_54$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1))], 64)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [detailRecord.value[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_55$1, [_cache[13] || (_cache[13] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_56$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_57$1, "—"))], 64)) : field.type === "flag" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [__props.render.deriveRecord(detailRecord.value)[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3073
+ key: 0,
3074
+ class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200/40",
3075
+ "data-testid": `collections-detail-flag-${key}`
3076
+ }, [_cache[14] || (_cache[14] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)], 8, _hoisted_58$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3077
+ key: 1,
3078
+ class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-slate-50 text-slate-400 border border-slate-200/20",
3079
+ "data-testid": `collections-detail-flag-${key}`
3080
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 9, _hoisted_59$1))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3081
+ key: 3,
3032
3082
  href: (0, vue.unref)(cui).recordHref?.(field.to, String(detailRecord.value[key])),
3033
3083
  tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(detailRecord.value[key])) ? void 0 : 0,
3034
3084
  role: "link",
@@ -3036,16 +3086,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3036
3086
  "data-testid": `collections-detail-ref-${key}`,
3037
3087
  onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])),
3038
3088
  onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["space"])]
3039
- }, (0, vue.toDisplayString)(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_58$1)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_59$1, (0, vue.toDisplayString)(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_60$1, (0, vue.toDisplayString)(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3040
- key: 5,
3089
+ }, (0, vue.toDisplayString)(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_60$1)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_61$1, (0, vue.toDisplayString)(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_62$1, (0, vue.toDisplayString)(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3090
+ key: 6,
3041
3091
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-2 py-0.5 rounded border border-indigo-100/50",
3042
3092
  "data-testid": `collections-detail-rollup-${key}`
3043
- }, (0, vue.toDisplayString)(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_61$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_62$1, [(0, vue.createElementVNode)("table", _hoisted_63$1, [(0, vue.createElementVNode)("thead", _hoisted_64$1, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.of, (subField, subKey) => {
3093
+ }, (0, vue.toDisplayString)(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_63$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_64$1, [(0, vue.createElementVNode)("table", _hoisted_65$1, [(0, vue.createElementVNode)("thead", _hoisted_66$1, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.of, (subField, subKey) => {
3044
3094
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
3045
3095
  key: subKey,
3046
3096
  class: "text-left px-4 py-2 font-bold"
3047
3097
  }, (0, vue.toDisplayString)(subField.label), 1);
3048
- }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_65$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
3098
+ }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_67$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
3049
3099
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
3050
3100
  key: rowIdx,
3051
3101
  class: "hover:bg-slate-50/50"
@@ -3053,48 +3103,48 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3053
3103
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("td", {
3054
3104
  key: subKey,
3055
3105
  class: "px-4 py-2 align-middle font-medium"
3056
- }, [subField.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row[subKey] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_66$1, "check_circle")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_67$1, "—"))], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3106
+ }, [subField.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row[subKey] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_68$1, "check_circle")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_69$1, "—"))], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3057
3107
  key: 1,
3058
3108
  class: (0, vue.normalizeClass)([subField.type === "money" ? "font-bold text-slate-800 tabular-nums" : ""])
3059
3109
  }, (0, vue.toDisplayString)(__props.render.formatSubCell(subField, row[subKey], detailRecord.value)), 3))]);
3060
3110
  }), 128))]);
3061
- }), 128))])])])) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_68$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_69$1, (0, vue.toDisplayString)(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionEmbedView_default, {
3062
- key: 9,
3111
+ }), 128))])])])) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_70$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_71$1, (0, vue.toDisplayString)(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionEmbedView_default, {
3112
+ key: 10,
3063
3113
  view: embedViews.value[key],
3064
3114
  "field-key": String(key)
3065
3115
  }, null, 8, ["view", "field-key"])) : field.type === "backlinks" && backlinksViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionBacklinksView_default, {
3066
- key: 10,
3116
+ key: 11,
3067
3117
  view: backlinksViews.value[key],
3068
3118
  "field-key": String(key)
3069
3119
  }, null, 8, ["view", "field-key"])) : field.type === "image" && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("img", {
3070
- key: 11,
3120
+ key: 12,
3071
3121
  src: (0, vue.unref)(resolveImageSrc)(String(detailRecord.value[key])),
3072
3122
  alt: field.label,
3073
3123
  class: "max-h-64 max-w-full object-contain rounded-lg border border-slate-200 bg-slate-50",
3074
3124
  "data-testid": `collections-detail-image-${key}`
3075
- }, null, 8, _hoisted_70$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3076
- key: 12,
3125
+ }, null, 8, _hoisted_72$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3126
+ key: 13,
3077
3127
  href: String(detailRecord.value[key]),
3078
3128
  target: "_blank",
3079
3129
  rel: "noopener noreferrer",
3080
3130
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3081
3131
  "data-testid": `collections-detail-url-${key}`
3082
- }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_71$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3083
- key: 13,
3132
+ }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_73$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3133
+ key: 14,
3084
3134
  href: __props.render.artifactUrl(detailRecord.value[key]) ?? void 0,
3085
3135
  target: "_blank",
3086
3136
  rel: "noopener noreferrer",
3087
3137
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3088
3138
  "data-testid": `collections-detail-file-${key}`
3089
- }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_72$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3090
- key: 14,
3139
+ }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_74$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3140
+ key: 15,
3091
3141
  href: __props.render.fileRoutePath(detailRecord.value[key]) ?? void 0,
3092
3142
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3093
3143
  "data-testid": `collections-detail-file-${key}`,
3094
3144
  onClick: ($event) => (0, vue.unref)(activatePathLink)($event, __props.render.fileRoutePath(detailRecord.value[key]) ?? "")
3095
- }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_73$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_74$1, (0, vue.toDisplayString)(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : (0, vue.createCommentVNode)("", true)], 64);
3096
- }), 128)), editing.value && __props.saveError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_75$1, (0, vue.toDisplayString)(__props.saveError), 1)) : (0, vue.createCommentVNode)("", true)]),
3097
- !editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_76$1, [(0, vue.createElementVNode)("label", _hoisted_77$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemChatLabel")), 1), (0, vue.createElementVNode)("div", _hoisted_78$1, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
3145
+ }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_75$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_76$1, (0, vue.toDisplayString)(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : (0, vue.createCommentVNode)("", true)], 64);
3146
+ }), 128)), editing.value && __props.saveError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_77$1, (0, vue.toDisplayString)(__props.saveError), 1)) : (0, vue.createCommentVNode)("", true)]),
3147
+ !editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_78$1, [(0, vue.createElementVNode)("label", _hoisted_79$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemChatLabel")), 1), (0, vue.createElementVNode)("div", _hoisted_80$1, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
3098
3148
  id: "collections-detail-chat-input",
3099
3149
  "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => chatMessage.value = $event),
3100
3150
  rows: "2",
@@ -3102,13 +3152,13 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3102
3152
  class: "flex-1 bg-slate-50 border border-slate-200/80 rounded-xl px-3 py-2 text-xs placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all resize-none",
3103
3153
  "data-testid": "collections-detail-chat-input",
3104
3154
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitItemChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitItemChat, ["ctrl"]), ["enter"])]
3105
- }, null, 40, _hoisted_79$1), [[vue.vModelText, chatMessage.value]]), (0, vue.createElementVNode)("button", {
3155
+ }, null, 40, _hoisted_81$1), [[vue.vModelText, chatMessage.value]]), (0, vue.createElementVNode)("button", {
3106
3156
  type: "button",
3107
3157
  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 flex items-center gap-1 shrink-0",
3108
3158
  disabled: !chatMessage.value.trim(),
3109
3159
  "data-testid": "collections-detail-chat-send",
3110
3160
  onClick: submitItemChat
3111
- }, [_cache[14] || (_cache[14] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)], 8, _hoisted_80$1)])])) : (0, vue.createCommentVNode)("", true)
3161
+ }, [_cache[15] || (_cache[15] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)], 8, _hoisted_82$1)])])) : (0, vue.createCommentVNode)("", true)
3112
3162
  ]),
3113
3163
  _: 1
3114
3164
  }, 40, ["data-testid"]);
@@ -3903,6 +3953,38 @@ function writeCollectionSort(slug, sort) {
3903
3953
  localStorage.setItem(SORT_STORAGE_KEY, JSON.stringify(all));
3904
3954
  } catch {}
3905
3955
  }
3956
+ var FLAG_FILTER_STORAGE_KEY = "collection_flag_filters";
3957
+ function isFlagFilterState(value) {
3958
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
3959
+ return Object.values(value).every((mode) => mode === "hide" || mode === "only");
3960
+ }
3961
+ function readAllFlagFilters() {
3962
+ try {
3963
+ const raw = localStorage.getItem(FLAG_FILTER_STORAGE_KEY);
3964
+ if (!raw) return {};
3965
+ const parsed = JSON.parse(raw);
3966
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
3967
+ const out = {};
3968
+ for (const [slug, value] of Object.entries(parsed)) if (isFlagFilterState(value)) out[slug] = value;
3969
+ return out;
3970
+ } catch {
3971
+ return {};
3972
+ }
3973
+ }
3974
+ /** The slug's persisted chip states ({} when none). A key whose flag no
3975
+ * longer exists in the schema is harmless — the chip list is derived
3976
+ * from the live schema, so a stale entry just never renders/filters. */
3977
+ function readCollectionFlagFilters(slug) {
3978
+ return readAllFlagFilters()[slug] ?? {};
3979
+ }
3980
+ /** Persist the slug's chip states; an empty state clears the entry. */
3981
+ function writeCollectionFlagFilters(slug, filters) {
3982
+ try {
3983
+ const all = Object.fromEntries(Object.entries(readAllFlagFilters()).filter(([key]) => key !== slug));
3984
+ if (Object.keys(filters).length > 0) all[slug] = filters;
3985
+ localStorage.setItem(FLAG_FILTER_STORAGE_KEY, JSON.stringify(all));
3986
+ } catch {}
3987
+ }
3906
3988
  //#endregion
3907
3989
  //#region src/vue/components/CollectionView.vue?vue&type=script&setup=true&lang.ts
3908
3990
  var _hoisted_1$6 = { class: "h-full flex flex-col bg-slate-50/30" };
@@ -3962,185 +4044,198 @@ var _hoisted_22$3 = ["placeholder", "aria-label"];
3962
4044
  var _hoisted_23$2 = ["aria-label"];
3963
4045
  var _hoisted_24$1 = { class: "flex items-center gap-2" };
3964
4046
  var _hoisted_25$1 = ["aria-label"];
3965
- var _hoisted_26$1 = ["aria-pressed"];
3966
- var _hoisted_27$1 = ["aria-pressed"];
3967
- var _hoisted_28 = ["aria-pressed"];
3968
- var _hoisted_29 = [
4047
+ var _hoisted_26$1 = [
4048
+ "title",
4049
+ "aria-label",
3969
4050
  "aria-pressed",
3970
4051
  "data-testid",
3971
4052
  "onClick"
3972
4053
  ];
3973
- var _hoisted_30 = { class: "material-icons text-sm" };
3974
- var _hoisted_31 = [
4054
+ var _hoisted_27$1 = {
4055
+ class: "material-icons text-sm",
4056
+ "aria-hidden": "true"
4057
+ };
4058
+ var _hoisted_28 = ["aria-label"];
4059
+ var _hoisted_29 = ["aria-pressed"];
4060
+ var _hoisted_30 = ["aria-pressed"];
4061
+ var _hoisted_31 = ["aria-pressed"];
4062
+ var _hoisted_32 = [
4063
+ "aria-pressed",
4064
+ "data-testid",
4065
+ "onClick"
4066
+ ];
4067
+ var _hoisted_33 = { class: "material-icons text-sm" };
4068
+ var _hoisted_34 = [
3975
4069
  "title",
3976
4070
  "aria-label",
3977
4071
  "aria-expanded"
3978
4072
  ];
3979
- var _hoisted_32 = {
4073
+ var _hoisted_35 = {
3980
4074
  key: 0,
3981
4075
  class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
3982
4076
  "data-testid": "collection-view-add-menu"
3983
4077
  };
3984
- var _hoisted_33 = ["title", "aria-label"];
3985
- var _hoisted_34 = ["value", "aria-label"];
3986
- var _hoisted_35 = ["value"];
3987
- var _hoisted_36 = ["value", "aria-label"];
3988
- var _hoisted_37 = ["value"];
3989
- var _hoisted_38 = {
3990
- key: 3,
4078
+ var _hoisted_36 = ["title", "aria-label"];
4079
+ var _hoisted_37 = ["value", "aria-label"];
4080
+ var _hoisted_38 = ["value"];
4081
+ var _hoisted_39 = ["value", "aria-label"];
4082
+ var _hoisted_40 = ["value"];
4083
+ var _hoisted_41 = {
4084
+ key: 4,
3991
4085
  class: "text-[10px] text-slate-400 font-bold uppercase tracking-wider select-none"
3992
4086
  };
3993
- var _hoisted_39 = {
4087
+ var _hoisted_42 = {
3994
4088
  key: 3,
3995
4089
  class: "mx-6 mt-4 rounded-xl border border-amber-200 bg-amber-50/60 p-4 text-sm text-amber-900 shadow-sm flex items-center gap-3",
3996
4090
  "data-testid": "collections-data-issues"
3997
4091
  };
3998
- var _hoisted_40 = { class: "flex-1" };
3999
- var _hoisted_41 = { class: "flex-1 overflow-auto" };
4000
- var _hoisted_42 = {
4092
+ var _hoisted_43 = { class: "flex-1" };
4093
+ var _hoisted_44 = { class: "flex-1 overflow-auto" };
4094
+ var _hoisted_45 = {
4001
4095
  key: 0,
4002
4096
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
4003
4097
  };
4004
- var _hoisted_43 = {
4098
+ var _hoisted_46 = {
4005
4099
  key: 1,
4006
4100
  class: "m-6 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3"
4007
4101
  };
4008
- var _hoisted_44 = { key: 2 };
4009
- var _hoisted_45 = {
4102
+ var _hoisted_47 = { key: 2 };
4103
+ var _hoisted_48 = {
4010
4104
  key: 3,
4011
4105
  class: "p-4"
4012
4106
  };
4013
- var _hoisted_46 = {
4107
+ var _hoisted_49 = {
4014
4108
  key: 4,
4015
4109
  class: "h-full flex flex-col"
4016
4110
  };
4017
- var _hoisted_47 = {
4111
+ var _hoisted_50 = {
4018
4112
  key: 0,
4019
4113
  class: "m-3 mb-0 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3",
4020
4114
  "data-testid": "collections-inline-error"
4021
4115
  };
4022
- var _hoisted_48 = { class: "flex-1" };
4023
- var _hoisted_49 = ["aria-label"];
4024
- var _hoisted_50 = { class: "flex-1 min-h-0 px-3 py-2" };
4025
- var _hoisted_51 = {
4116
+ var _hoisted_51 = { class: "flex-1" };
4117
+ var _hoisted_52 = ["aria-label"];
4118
+ var _hoisted_53 = { class: "flex-1 min-h-0 px-3 py-2" };
4119
+ var _hoisted_54 = {
4026
4120
  key: 5,
4027
4121
  class: "h-full",
4028
4122
  "data-testid": "collection-custom-view-body"
4029
4123
  };
4030
- var _hoisted_52 = {
4124
+ var _hoisted_55 = {
4031
4125
  key: 6,
4032
4126
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
4033
4127
  };
4034
- var _hoisted_53 = { class: "font-semibold text-slate-600" };
4035
- var _hoisted_54 = {
4128
+ var _hoisted_56 = { class: "font-semibold text-slate-600" };
4129
+ var _hoisted_57 = {
4036
4130
  key: 7,
4037
4131
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
4038
4132
  };
4039
- var _hoisted_55 = { class: "font-semibold text-slate-600" };
4040
- var _hoisted_56 = {
4133
+ var _hoisted_58 = { class: "font-semibold text-slate-600" };
4134
+ var _hoisted_59 = {
4041
4135
  key: 8,
4042
4136
  class: "overflow-x-auto [container-type:inline-size]"
4043
4137
  };
4044
- var _hoisted_57 = {
4138
+ var _hoisted_60 = {
4045
4139
  key: 0,
4046
4140
  class: "m-4 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3",
4047
4141
  "data-testid": "collections-inline-error"
4048
4142
  };
4049
- var _hoisted_58 = { class: "flex-1" };
4050
- var _hoisted_59 = ["aria-label"];
4051
- var _hoisted_60 = { class: "min-w-full text-xs" };
4052
- var _hoisted_61 = { class: "bg-slate-50 border-b border-slate-200" };
4053
- var _hoisted_62 = ["aria-sort"];
4054
- var _hoisted_63 = { class: "flex items-center gap-1" };
4055
- var _hoisted_64 = ["title"];
4056
- var _hoisted_65 = [
4143
+ var _hoisted_61 = { class: "flex-1" };
4144
+ var _hoisted_62 = ["aria-label"];
4145
+ var _hoisted_63 = { class: "min-w-full text-xs" };
4146
+ var _hoisted_64 = { class: "bg-slate-50 border-b border-slate-200" };
4147
+ var _hoisted_65 = ["aria-sort"];
4148
+ var _hoisted_66 = { class: "flex items-center gap-1" };
4149
+ var _hoisted_67 = ["title"];
4150
+ var _hoisted_68 = [
4057
4151
  "data-testid",
4058
4152
  "aria-label",
4059
4153
  "onClick",
4060
4154
  "onPointerenter"
4061
4155
  ];
4062
- var _hoisted_66 = { class: "material-icons text-base align-middle" };
4063
- var _hoisted_67 = { class: "divide-y divide-slate-100 bg-white" };
4064
- var _hoisted_68 = [
4156
+ var _hoisted_69 = { class: "material-icons text-base align-middle" };
4157
+ var _hoisted_70 = { class: "divide-y divide-slate-100 bg-white" };
4158
+ var _hoisted_71 = [
4065
4159
  "aria-label",
4066
4160
  "data-testid",
4067
4161
  "onClick",
4068
4162
  "onKeydown"
4069
4163
  ];
4070
- var _hoisted_69 = [
4164
+ var _hoisted_72 = [
4071
4165
  "checked",
4072
4166
  "disabled",
4073
4167
  "data-testid",
4074
4168
  "aria-label",
4075
4169
  "onChange"
4076
4170
  ];
4077
- var _hoisted_70 = [
4171
+ var _hoisted_73 = [
4078
4172
  "checked",
4079
4173
  "disabled",
4080
4174
  "data-testid",
4081
4175
  "aria-label",
4082
4176
  "onChange"
4083
4177
  ];
4084
- var _hoisted_71 = {
4085
- key: 2,
4178
+ var _hoisted_74 = ["data-testid", "aria-label"];
4179
+ var _hoisted_75 = {
4180
+ key: 3,
4086
4181
  class: "block truncate"
4087
4182
  };
4088
- var _hoisted_72 = [
4183
+ var _hoisted_76 = [
4089
4184
  "href",
4090
4185
  "tabindex",
4091
4186
  "data-testid",
4092
4187
  "onClick",
4093
4188
  "onKeydown"
4094
4189
  ];
4095
- var _hoisted_73 = [
4190
+ var _hoisted_77 = [
4096
4191
  "value",
4097
4192
  "disabled",
4098
4193
  "data-testid",
4099
4194
  "aria-label",
4100
4195
  "onChange"
4101
4196
  ];
4102
- var _hoisted_74 = {
4197
+ var _hoisted_78 = {
4103
4198
  key: 0,
4104
4199
  value: ""
4105
4200
  };
4106
- var _hoisted_75 = ["value"];
4107
- var _hoisted_76 = {
4108
- key: 4,
4201
+ var _hoisted_79 = ["value"];
4202
+ var _hoisted_80 = {
4203
+ key: 5,
4109
4204
  class: "block truncate tabular-nums font-semibold text-slate-900"
4110
4205
  };
4111
- var _hoisted_77 = {
4112
- key: 5,
4206
+ var _hoisted_81 = {
4207
+ key: 6,
4113
4208
  class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-lg text-[10px] font-bold bg-slate-100 text-slate-600 border border-slate-200/40"
4114
4209
  };
4115
- var _hoisted_78 = {
4116
- key: 6,
4210
+ var _hoisted_82 = {
4211
+ key: 7,
4117
4212
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-1.5 py-0.5 rounded border border-indigo-100/50"
4118
4213
  };
4119
- var _hoisted_79 = ["data-testid"];
4120
- var _hoisted_80 = ["href", "data-testid"];
4121
- var _hoisted_81 = ["href", "data-testid"];
4122
- var _hoisted_82 = [
4214
+ var _hoisted_83 = ["data-testid"];
4215
+ var _hoisted_84 = ["href", "data-testid"];
4216
+ var _hoisted_85 = ["href", "data-testid"];
4217
+ var _hoisted_86 = [
4123
4218
  "href",
4124
4219
  "data-testid",
4125
4220
  "onClick"
4126
4221
  ];
4127
- var _hoisted_83 = {
4128
- key: 11,
4222
+ var _hoisted_87 = {
4223
+ key: 12,
4129
4224
  class: "block truncate text-slate-600"
4130
4225
  };
4131
- var _hoisted_84 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4132
- var _hoisted_85 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4133
- var _hoisted_86 = { class: "flex-1" };
4134
- var _hoisted_87 = {
4226
+ var _hoisted_88 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4227
+ var _hoisted_89 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4228
+ var _hoisted_90 = { class: "flex-1" };
4229
+ var _hoisted_91 = {
4135
4230
  id: "collections-chat-title",
4136
4231
  class: "text-sm font-bold text-slate-800 uppercase tracking-wide"
4137
4232
  };
4138
- var _hoisted_88 = { class: "text-xs text-slate-400 font-semibold" };
4139
- var _hoisted_89 = ["aria-label"];
4140
- var _hoisted_90 = { class: "px-6 py-5" };
4141
- var _hoisted_91 = ["placeholder", "onKeydown"];
4142
- var _hoisted_92 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
4143
- var _hoisted_93 = ["disabled"];
4233
+ var _hoisted_92 = { class: "text-xs text-slate-400 font-semibold" };
4234
+ var _hoisted_93 = ["aria-label"];
4235
+ var _hoisted_94 = { class: "px-6 py-5" };
4236
+ var _hoisted_95 = ["placeholder", "onKeydown"];
4237
+ var _hoisted_96 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
4238
+ var _hoisted_97 = ["disabled"];
4144
4239
  /** `slug` / `selected` are supplied only in EMBEDDED mode (the
4145
4240
  * `presentCollection` chat card mounts this component and drives both
4146
4241
  * from the tool result). In standalone route mode (the
@@ -4151,6 +4246,7 @@ var _hoisted_93 = ["disabled"];
4151
4246
  * is our "rendered inside a chat" signal. When set, chat-triggering
4152
4247
  * actions send into the current session instead of spawning a new
4153
4248
  * chat (see `runAction` / `submitChat`). */
4249
+ var COMPLETION_CHIP_KEY = "__completion";
4154
4250
  var LIVE_REFRESH_DEBOUNCE_MS = 150;
4155
4251
  //#endregion
4156
4252
  //#region src/vue/components/CollectionView.vue
@@ -4277,6 +4373,84 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4277
4373
  if (!query) return items.value;
4278
4374
  return items.value.filter((item) => itemMatchesQuery(item, query));
4279
4375
  });
4376
+ /** Chip key (state/testid/localStorage) for the synthesized
4377
+ * legacy-completion chip. Field names are unrestricted strings, so a
4378
+ * schema COULD declare a field with this exact name — the chip list
4379
+ * below skips synthesizing in that case, and the predicate dispatch
4380
+ * keys off the structural `synthetic` marker, never this string. */
4381
+ function storedFlagFiltersFor(slug) {
4382
+ return slug ? readCollectionFlagFilters(slug) : {};
4383
+ }
4384
+ const flagFilters = (0, vue.ref)(storedFlagFiltersFor(activeSlug.value));
4385
+ const flagChips = (0, vue.computed)(() => {
4386
+ const schema = collection.value?.schema;
4387
+ if (!schema) return [];
4388
+ const chips = Object.entries(schema.fields).filter(([, field]) => field.type === "flag").map(([key, field]) => ({
4389
+ key,
4390
+ label: field.label ?? key
4391
+ }));
4392
+ if (schema.completionField && schema.completionDoneValues && schema.fields[schema.completionField]?.type !== "flag" && schema.fields[COMPLETION_CHIP_KEY] === void 0) chips.push({
4393
+ key: COMPLETION_CHIP_KEY,
4394
+ label: t("collectionsView.flagDoneChip"),
4395
+ synthetic: true
4396
+ });
4397
+ return chips;
4398
+ });
4399
+ /** Own-property read of a chip's active mode. Field names may shadow
4400
+ * `Object.prototype` members (`toString`, `valueOf`, …) — a plain
4401
+ * `filters[key]` on such a key reads the inherited function, which
4402
+ * renders as an "active" chip that can never cycle (Codex review on
4403
+ * PR #2176). Every chip-state read goes through here. */
4404
+ function flagFilterMode(key) {
4405
+ const filters = flagFilters.value;
4406
+ return Object.hasOwn(filters, key) ? filters[key] : void 0;
4407
+ }
4408
+ /** A flag FIELD's computed boolean for one row (list cells + sort):
4409
+ * the enriched record's value, so a flag over derived/rollup inputs
4410
+ * reads correctly. */
4411
+ function flagValueOf(key, item) {
4412
+ return render.deriveRecord(item)[key] === true;
4413
+ }
4414
+ /** The chip's boolean for one row — `itemIsDone` for the synthesized
4415
+ * completion chip, the computed flag value otherwise. */
4416
+ function chipMatches(chip, item) {
4417
+ const schema = collection.value?.schema;
4418
+ if (!schema) return false;
4419
+ return chip.synthetic ? (0, _mulmoclaude_core_collection.itemIsDone)(schema, item) : flagValueOf(chip.key, item);
4420
+ }
4421
+ /** `filteredItems` further narrowed by every ACTIVE chip (AND). Consumed
4422
+ * only by the table (sortedItems / count summary / empty state). */
4423
+ const tableFilteredItems = (0, vue.computed)(() => {
4424
+ const active = flagChips.value.filter((chip) => flagFilterMode(chip.key) !== void 0);
4425
+ if (active.length === 0) return filteredItems.value;
4426
+ return filteredItems.value.filter((item) => active.every((chip) => chipMatches(chip, item) === (flagFilterMode(chip.key) === "only")));
4427
+ });
4428
+ /** Cycle a chip all → hide → only → all. */
4429
+ function cycleFlagFilter(key) {
4430
+ const current = flagFilterMode(key);
4431
+ const next = current === void 0 ? "hide" : current === "hide" ? "only" : void 0;
4432
+ const rest = Object.fromEntries(Object.entries(flagFilters.value).filter(([entry]) => entry !== key));
4433
+ flagFilters.value = next ? {
4434
+ ...rest,
4435
+ [key]: next
4436
+ } : rest;
4437
+ }
4438
+ function flagChipIcon(key) {
4439
+ const mode = flagFilterMode(key);
4440
+ return mode === "hide" ? "visibility_off" : mode === "only" ? "filter_alt" : "visibility";
4441
+ }
4442
+ function flagChipClass(key) {
4443
+ const mode = flagFilterMode(key);
4444
+ if (mode === "hide") return "bg-slate-600 text-white";
4445
+ if (mode === "only") return "bg-indigo-600 text-white";
4446
+ return "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50";
4447
+ }
4448
+ function flagChipTitle(chip) {
4449
+ const mode = flagFilterMode(chip.key);
4450
+ if (mode === "hide") return t("collectionsView.flagFilterHide", { label: chip.label });
4451
+ if (mode === "only") return t("collectionsView.flagFilterOnly", { label: chip.label });
4452
+ return t("collectionsView.flagFilterAll", { label: chip.label });
4453
+ }
4280
4454
  function storedSortFor(slug) {
4281
4455
  return slug && readCollectionSort(slug) || null;
4282
4456
  }
@@ -4323,10 +4497,11 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4323
4497
  default: return (0, _mulmoclaude_core_collection.stringSortValue)(raw);
4324
4498
  }
4325
4499
  }
4326
- /** Comparable value for one row under the active field. Toggle and derived
4327
- * need the whole record; every other type keys off the raw cell. */
4500
+ /** Comparable value for one row under the active field. Toggle, flag, and
4501
+ * derived need the whole record; every other type keys off the raw cell. */
4328
4502
  function sortValueOf(field, key, item) {
4329
4503
  if (field.type === "toggle") return (0, _mulmoclaude_core_collection.boolSortValue)(toggleChecked(item, field));
4504
+ if (field.type === "flag") return (0, _mulmoclaude_core_collection.boolSortValue)(flagValueOf(key, item));
4330
4505
  if (field.type === "derived") return derivedSortValue(field, key, item);
4331
4506
  return scalarSortValue(field, item[key]);
4332
4507
  }
@@ -4342,8 +4517,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4342
4517
  const sortedItems = (0, vue.computed)(() => {
4343
4518
  const state = sortState.value;
4344
4519
  const field = state ? collection.value?.schema.fields[state.field] : void 0;
4345
- if (!state || !field) return filteredItems.value;
4346
- return (0, _mulmoclaude_core_collection.sortItems)(filteredItems.value, state.direction, (item) => sortValueOf(field, state.field, item));
4520
+ if (!state || !field) return tableFilteredItems.value;
4521
+ return (0, _mulmoclaude_core_collection.sortItems)(tableFilteredItems.value, state.direction, (item) => sortValueOf(field, state.field, item));
4347
4522
  });
4348
4523
  /** Stringified primary-key value for a row (the row's stable identity). */
4349
4524
  function rowId(item) {
@@ -5289,6 +5464,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5289
5464
  kanbanOverride.value = null;
5290
5465
  addMenuOpen.value = false;
5291
5466
  sortState.value = storedSortFor(slug);
5467
+ flagFilters.value = storedFlagFiltersFor(slug);
5292
5468
  }
5293
5469
  if (slug) loadCollection(slug);
5294
5470
  else {
@@ -5343,6 +5519,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5343
5519
  calendarAnchorField,
5344
5520
  kanbanGroupField,
5345
5521
  sortState,
5522
+ flagFilters,
5346
5523
  loading
5347
5524
  ], () => {
5348
5525
  if (embedded.value) emit("viewStateChange", {
@@ -5353,6 +5530,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5353
5530
  if (activeSlug.value && !loading.value && collection.value) {
5354
5531
  if (!embedded.value) writeCollectionViewMode(activeSlug.value, activeView.value);
5355
5532
  writeCollectionSort(activeSlug.value, sortState.value);
5533
+ writeCollectionFlagFilters(activeSlug.value, flagFilters.value);
5356
5534
  }
5357
5535
  });
5358
5536
  (0, vue.watch)(activeSelected, () => {
@@ -5461,8 +5639,25 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5461
5639
  onClick: _cache[2] || (_cache[2] = ($event) => searchQuery.value = "")
5462
5640
  }, [..._cache[34] || (_cache[34] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_23$2)) : (0, vue.createCommentVNode)("", true)
5463
5641
  ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_24$1, [
5464
- !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5642
+ activeView.value === "table" && flagChips.value.length > 0 && items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5465
5643
  key: 0,
5644
+ class: "flex items-center gap-0.5",
5645
+ role: "group",
5646
+ "aria-label": (0, vue.unref)(t)("collectionsView.flagFilterGroup")
5647
+ }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(flagChips.value, (chip) => {
5648
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5649
+ key: chip.key,
5650
+ type: "button",
5651
+ class: (0, vue.normalizeClass)(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", flagChipClass(chip.key)]),
5652
+ title: flagChipTitle(chip),
5653
+ "aria-label": flagChipTitle(chip),
5654
+ "aria-pressed": flagFilterMode(chip.key) !== void 0,
5655
+ "data-testid": `collections-flag-chip-${chip.key}`,
5656
+ onClick: ($event) => cycleFlagFilter(chip.key)
5657
+ }, [(0, vue.createElementVNode)("span", _hoisted_27$1, (0, vue.toDisplayString)(flagChipIcon(chip.key)), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(chip.label), 1)], 10, _hoisted_26$1);
5658
+ }), 128))], 8, _hoisted_25$1)) : (0, vue.createCommentVNode)("", true),
5659
+ !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5660
+ key: 1,
5466
5661
  class: "flex gap-0.5",
5467
5662
  role: "group",
5468
5663
  "aria-label": (0, vue.unref)(t)("collectionsView.viewToggle")
@@ -5473,7 +5668,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5473
5668
  "aria-pressed": activeView.value === "table",
5474
5669
  "data-testid": "collection-view-toggle-table",
5475
5670
  onClick: _cache[3] || (_cache[3] = ($event) => setView("table"))
5476
- }, [_cache[36] || (_cache[36] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "table_rows", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewTable")), 1)], 10, _hoisted_26$1),
5671
+ }, [_cache[36] || (_cache[36] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "table_rows", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewTable")), 1)], 10, _hoisted_29),
5477
5672
  hasCalendar.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5478
5673
  key: 0,
5479
5674
  type: "button",
@@ -5481,7 +5676,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5481
5676
  "aria-pressed": activeView.value === "calendar",
5482
5677
  "data-testid": "collection-view-toggle-calendar",
5483
5678
  onClick: _cache[4] || (_cache[4] = ($event) => setView("calendar"))
5484
- }, [_cache[37] || (_cache[37] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "calendar_month", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_27$1)) : (0, vue.createCommentVNode)("", true),
5679
+ }, [_cache[37] || (_cache[37] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "calendar_month", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_30)) : (0, vue.createCommentVNode)("", true),
5485
5680
  hasKanban.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5486
5681
  key: 1,
5487
5682
  type: "button",
@@ -5489,7 +5684,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5489
5684
  "aria-pressed": activeView.value === "kanban",
5490
5685
  "data-testid": "collection-view-toggle-kanban",
5491
5686
  onClick: _cache[5] || (_cache[5] = ($event) => setView("kanban"))
5492
- }, [_cache[38] || (_cache[38] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "view_kanban", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_28)) : (0, vue.createCommentVNode)("", true),
5687
+ }, [_cache[38] || (_cache[38] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "view_kanban", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_31)) : (0, vue.createCommentVNode)("", true),
5493
5688
  ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(customViews.value, (cv) => {
5494
5689
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5495
5690
  key: cv.id,
@@ -5498,7 +5693,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5498
5693
  "aria-pressed": activeView.value === (0, vue.unref)(customViewKey)(cv.id),
5499
5694
  "data-testid": `collection-view-custom-${cv.id}`,
5500
5695
  onClick: ($event) => setCustomView(cv.id)
5501
- }, [(0, vue.createElementVNode)("span", _hoisted_30, (0, vue.toDisplayString)(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(cv.label), 1)], 10, _hoisted_29);
5696
+ }, [(0, vue.createElementVNode)("span", _hoisted_33, (0, vue.toDisplayString)(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(cv.label), 1)], 10, _hoisted_32);
5502
5697
  }), 128)),
5503
5698
  canAddCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5504
5699
  key: 2,
@@ -5513,7 +5708,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5513
5708
  "aria-expanded": addMenuOpen.value,
5514
5709
  "data-testid": "collection-view-add",
5515
5710
  onClick: onAddViewClick
5516
- }, [..._cache[39] || (_cache[39] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_31), addMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_32, [(0, vue.createElementVNode)("button", {
5711
+ }, [..._cache[39] || (_cache[39] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_34), addMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_35, [(0, vue.createElementVNode)("button", {
5517
5712
  type: "button",
5518
5713
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5519
5714
  "data-testid": "collection-view-add-desktop",
@@ -5532,10 +5727,10 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5532
5727
  "aria-label": (0, vue.unref)(t)("collectionsView.config.open"),
5533
5728
  "data-testid": "collection-config-open",
5534
5729
  onClick: _cache[8] || (_cache[8] = ($event) => configOpen.value = true)
5535
- }, [..._cache[42] || (_cache[42] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_33)) : (0, vue.createCommentVNode)("", true)
5536
- ], 8, _hoisted_25$1)) : (0, vue.createCommentVNode)("", true),
5730
+ }, [..._cache[42] || (_cache[42] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_36)) : (0, vue.createCommentVNode)("", true)
5731
+ ], 8, _hoisted_28)) : (0, vue.createCommentVNode)("", true),
5537
5732
  calendarActive.value && dateFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5538
- key: 1,
5733
+ key: 2,
5539
5734
  value: calendarAnchorField.value,
5540
5735
  class: "h-8 px-2 rounded border border-slate-200 bg-white text-xs font-semibold text-slate-600 focus:outline-none focus:border-indigo-500 cursor-pointer",
5541
5736
  "aria-label": (0, vue.unref)(t)("collectionsView.calendarFieldLabel"),
@@ -5545,10 +5740,10 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5545
5740
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5546
5741
  key,
5547
5742
  value: key
5548
- }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_35);
5549
- }), 128))], 40, _hoisted_34)) : (0, vue.createCommentVNode)("", true),
5743
+ }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_38);
5744
+ }), 128))], 40, _hoisted_37)) : (0, vue.createCommentVNode)("", true),
5550
5745
  kanbanActive.value && enumFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5551
- key: 2,
5746
+ key: 3,
5552
5747
  value: kanbanGroupField.value,
5553
5748
  class: "h-8 px-2 rounded border border-slate-200 bg-white text-xs font-semibold text-slate-600 focus:outline-none focus:border-indigo-500 cursor-pointer",
5554
5749
  "aria-label": (0, vue.unref)(t)("collectionsView.kanbanFieldLabel"),
@@ -5558,16 +5753,16 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5558
5753
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5559
5754
  key,
5560
5755
  value: key
5561
- }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_37);
5562
- }), 128))], 40, _hoisted_36)) : (0, vue.createCommentVNode)("", true),
5563
- items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_38, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.searchSummary", {
5564
- shown: filteredItems.value.length,
5756
+ }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_40);
5757
+ }), 128))], 40, _hoisted_39)) : (0, vue.createCommentVNode)("", true),
5758
+ items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_41, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.searchSummary", {
5759
+ shown: activeView.value === "table" ? tableFilteredItems.value.length : filteredItems.value.length,
5565
5760
  total: items.value.length
5566
5761
  })), 1)) : (0, vue.createCommentVNode)("", true)
5567
5762
  ])])) : (0, vue.createCommentVNode)("", true),
5568
- collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_39, [
5763
+ collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_42, [
5569
5764
  _cache[44] || (_cache[44] = (0, vue.createElementVNode)("span", { class: "material-icons text-amber-600" }, "warning", -1)),
5570
- (0, vue.createElementVNode)("span", _hoisted_40, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5765
+ (0, vue.createElementVNode)("span", _hoisted_43, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5571
5766
  (0, vue.createElementVNode)("button", {
5572
5767
  type: "button",
5573
5768
  class: "h-8 px-2.5 flex items-center gap-1 rounded border border-amber-300 bg-white hover:bg-amber-100 text-amber-700 font-bold text-xs transition-colors",
@@ -5575,7 +5770,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5575
5770
  onClick: repairCollection
5576
5771
  }, [_cache[43] || (_cache[43] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "build", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.repair")), 1)])
5577
5772
  ])) : (0, vue.createCommentVNode)("", true),
5578
- (0, vue.createElementVNode)("div", _hoisted_41, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_42, [_cache[45] || (_cache[45] = (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_43, [_cache[46] || (_cache[46] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(loadError.value === "not-found" ? (0, vue.unref)(t)("collectionsView.notFound") : `${(0, vue.unref)(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_44)) : calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_45, [(0, vue.createVNode)(CollectionCalendarView_default, {
5773
+ (0, vue.createElementVNode)("div", _hoisted_44, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_45, [_cache[45] || (_cache[45] = (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_46, [_cache[46] || (_cache[46] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(loadError.value === "not-found" ? (0, vue.unref)(t)("collectionsView.notFound") : `${(0, vue.unref)(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_47)) : calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_48, [(0, vue.createVNode)(CollectionCalendarView_default, {
5579
5774
  schema: collection.value.schema,
5580
5775
  items: filteredItems.value,
5581
5776
  "anchor-field": calendarAnchorField.value,
@@ -5664,16 +5859,16 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5664
5859
  "selected",
5665
5860
  "can-create",
5666
5861
  "show-detail"
5667
- ])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_46, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_47, [
5862
+ ])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_49, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_50, [
5668
5863
  _cache[48] || (_cache[48] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5669
- (0, vue.createElementVNode)("span", _hoisted_48, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5864
+ (0, vue.createElementVNode)("span", _hoisted_51, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5670
5865
  (0, vue.createElementVNode)("button", {
5671
5866
  type: "button",
5672
5867
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5673
5868
  "aria-label": (0, vue.unref)(t)("common.close"),
5674
5869
  onClick: _cache[13] || (_cache[13] = ($event) => inlineError.value = null)
5675
- }, [..._cache[47] || (_cache[47] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_49)
5676
- ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_50, [(0, vue.createVNode)(CollectionKanbanView_default, {
5870
+ }, [..._cache[47] || (_cache[47] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_52)
5871
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_53, [(0, vue.createVNode)(CollectionKanbanView_default, {
5677
5872
  schema: collection.value.schema,
5678
5873
  items: filteredItems.value,
5679
5874
  "group-field": kanbanGroupField.value,
@@ -5689,7 +5884,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5689
5884
  "selected",
5690
5885
  "notified",
5691
5886
  "readonly"
5692
- ])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_51, [activeCustomView.value.target === "mobile" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRemoteViewPreview_default, {
5887
+ ])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_54, [activeCustomView.value.target === "mobile" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRemoteViewPreview_default, {
5693
5888
  key: 0,
5694
5889
  slug: collection.value.slug,
5695
5890
  view: activeCustomView.value,
@@ -5700,32 +5895,32 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5700
5895
  view: activeCustomView.value,
5701
5896
  onOpenItem: onCustomViewOpenItem,
5702
5897
  onStartChat: onCustomViewStartChat
5703
- }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_52, [_cache[49] || (_cache[49] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), (0, vue.createElementVNode)("p", _hoisted_53, (0, vue.toDisplayString)((0, vue.unref)(t)(isReadOnly.value ? "collectionsView.itemsEmptyReadonly" : "collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_54, [
5898
+ }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_55, [_cache[49] || (_cache[49] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), (0, vue.createElementVNode)("p", _hoisted_56, (0, vue.toDisplayString)((0, vue.unref)(t)(isReadOnly.value ? "collectionsView.itemsEmptyReadonly" : "collectionsView.itemsEmpty")), 1)])) : tableFilteredItems.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_57, [
5704
5899
  _cache[50] || (_cache[50] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
5705
- (0, vue.createElementVNode)("p", _hoisted_55, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noMatchingItems")), 1),
5900
+ (0, vue.createElementVNode)("p", _hoisted_58, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noMatchingItems")), 1),
5706
5901
  (0, vue.createElementVNode)("button", {
5707
5902
  type: "button",
5708
5903
  class: "text-xs text-indigo-600 font-semibold hover:underline",
5709
- onClick: _cache[14] || (_cache[14] = ($event) => searchQuery.value = "")
5904
+ onClick: _cache[14] || (_cache[14] = ($event) => (searchQuery.value = "", flagFilters.value = {}))
5710
5905
  }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.clearSearch")), 1)
5711
- ])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_56, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_57, [
5906
+ ])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_59, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_60, [
5712
5907
  _cache[52] || (_cache[52] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5713
- (0, vue.createElementVNode)("span", _hoisted_58, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5908
+ (0, vue.createElementVNode)("span", _hoisted_61, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5714
5909
  (0, vue.createElementVNode)("button", {
5715
5910
  type: "button",
5716
5911
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5717
5912
  "aria-label": (0, vue.unref)(t)("common.close"),
5718
5913
  onClick: _cache[15] || (_cache[15] = ($event) => inlineError.value = null)
5719
- }, [..._cache[51] || (_cache[51] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_59)
5720
- ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table", _hoisted_60, [(0, vue.createElementVNode)("thead", null, [(0, vue.createElementVNode)("tr", _hoisted_61, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(listColumnFields.value, ([key, field]) => {
5914
+ }, [..._cache[51] || (_cache[51] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_62)
5915
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table", _hoisted_63, [(0, vue.createElementVNode)("thead", null, [(0, vue.createElementVNode)("tr", _hoisted_64, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(listColumnFields.value, ([key, field]) => {
5721
5916
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
5722
5917
  key,
5723
5918
  "aria-sort": (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? sortAriaValue(key) : void 0,
5724
5919
  class: "px-5 py-3 font-bold text-slate-500 text-left uppercase tracking-wider whitespace-nowrap"
5725
- }, [(0, vue.createElementVNode)("div", _hoisted_63, [(0, vue.createElementVNode)("span", {
5920
+ }, [(0, vue.createElementVNode)("div", _hoisted_66, [(0, vue.createElementVNode)("span", {
5726
5921
  class: "truncate max-w-[14rem]",
5727
5922
  title: field.label
5728
- }, (0, vue.toDisplayString)(field.label), 9, _hoisted_64), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5923
+ }, (0, vue.toDisplayString)(field.label), 9, _hoisted_67), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5729
5924
  key: 0,
5730
5925
  type: "button",
5731
5926
  class: (0, vue.normalizeClass)(["inline-flex items-center justify-center rounded p-0.5 -my-1 leading-none transition-colors", sortButtonClass(key)]),
@@ -5734,8 +5929,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5734
5929
  onClick: (0, vue.withModifiers)(($event) => cycleSort(key), ["stop"]),
5735
5930
  onPointerenter: ($event) => hoveredSortKey.value = key,
5736
5931
  onPointerleave: _cache[16] || (_cache[16] = ($event) => hoveredSortKey.value = null)
5737
- }, [(0, vue.createElementVNode)("span", _hoisted_66, (0, vue.toDisplayString)(sortIconName(key)), 1)], 42, _hoisted_65)) : (0, vue.createCommentVNode)("", true)])], 8, _hoisted_62);
5738
- }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_67, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(sortedItems.value, (item) => {
5932
+ }, [(0, vue.createElementVNode)("span", _hoisted_69, (0, vue.toDisplayString)(sortIconName(key)), 1)], 42, _hoisted_68)) : (0, vue.createCommentVNode)("", true)])], 8, _hoisted_65);
5933
+ }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_70, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(sortedItems.value, (item) => {
5739
5934
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
5740
5935
  key: String(item[collection.value.schema.primaryKey] ?? ""),
5741
5936
  class: (0, vue.normalizeClass)(["hover:bg-slate-50/70 cursor-pointer transition-colors focus:outline-none focus:bg-indigo-50/30", isRowOpen(item) || isEditingRow(item) ? "bg-indigo-50/40" : ""]),
@@ -5759,7 +5954,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5759
5954
  "aria-label": field.label,
5760
5955
  onClick: _cache[17] || (_cache[17] = (0, vue.withModifiers)(() => {}, ["stop"])),
5761
5956
  onChange: ($event) => commitToggle(item, field)
5762
- }, null, 40, _hoisted_69)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
5957
+ }, null, 40, _hoisted_72)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
5763
5958
  key: 1,
5764
5959
  type: "checkbox",
5765
5960
  checked: item[key] === true,
@@ -5769,7 +5964,13 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5769
5964
  "aria-label": field.label,
5770
5965
  onClick: _cache[18] || (_cache[18] = (0, vue.withModifiers)(() => {}, ["stop"])),
5771
5966
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.checked)
5772
- }, null, 40, _hoisted_70)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_71, [(0, vue.createElementVNode)("a", {
5967
+ }, null, 40, _hoisted_73)) : field.type === "flag" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
5968
+ key: 2,
5969
+ class: (0, vue.normalizeClass)(["material-icons text-lg align-middle", flagValueOf(String(key), item) ? "text-emerald-600" : "text-slate-300"]),
5970
+ "data-testid": `collections-flag-${key}-${item[collection.value.schema.primaryKey]}`,
5971
+ "aria-label": `${field.label}: ${(0, vue.unref)(t)(flagValueOf(String(key), item) ? "common.yes" : "common.no")}`,
5972
+ role: "img"
5973
+ }, (0, vue.toDisplayString)(flagValueOf(String(key), item) ? "check_circle" : "radio_button_unchecked"), 11, _hoisted_74)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_75, [(0, vue.createElementVNode)("a", {
5773
5974
  href: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])),
5774
5975
  tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])) ? void 0 : 0,
5775
5976
  role: "link",
@@ -5777,8 +5978,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5777
5978
  "data-testid": `collections-ref-link-${key}-${item[key]}`,
5778
5979
  onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true),
5779
5980
  onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true), ["space"])]
5780
- }, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41, _hoisted_72)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5781
- key: 3,
5981
+ }, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41, _hoisted_76)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5982
+ key: 4,
5782
5983
  value: item[key] == null ? "" : String(item[key]),
5783
5984
  disabled: isReadOnly.value || isRowInlineSaving(item),
5784
5985
  class: (0, vue.normalizeClass)(["rounded-lg border px-2 py-0.5 text-[11px] font-semibold focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed", enumControlClass(String(key), item[key])]),
@@ -5786,39 +5987,39 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5786
5987
  "aria-label": field.label,
5787
5988
  onClick: _cache[19] || (_cache[19] = (0, vue.withModifiers)(() => {}, ["stop"])),
5788
5989
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.value)
5789
- }, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option", _hoisted_74, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1)) : (0, vue.createCommentVNode)("", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.values, (value) => {
5990
+ }, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option", _hoisted_78, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1)) : (0, vue.createCommentVNode)("", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.values, (value) => {
5790
5991
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5791
5992
  key: value,
5792
5993
  value
5793
- }, (0, vue.toDisplayString)(value), 9, _hoisted_75);
5794
- }), 128))], 42, _hoisted_73)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_76, (0, vue.toDisplayString)((0, vue.unref)(formatMoney)(item[key], (0, vue.unref)(resolveCurrency)(field, item), (0, vue.unref)(locale))), 1)) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_77, [_cache[53] || (_cache[53] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "list", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(tableSummary(item[key])), 1)])) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_78, (0, vue.toDisplayString)((0, vue.unref)(derivedDisplay)(field, (0, vue.unref)(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
5795
- key: 7,
5994
+ }, (0, vue.toDisplayString)(value), 9, _hoisted_79);
5995
+ }), 128))], 42, _hoisted_77)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_80, (0, vue.toDisplayString)((0, vue.unref)(formatMoney)(item[key], (0, vue.unref)(resolveCurrency)(field, item), (0, vue.unref)(locale))), 1)) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_81, [_cache[53] || (_cache[53] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "list", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(tableSummary(item[key])), 1)])) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_82, (0, vue.toDisplayString)((0, vue.unref)(derivedDisplay)(field, (0, vue.unref)(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
5996
+ key: 8,
5796
5997
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-1.5 py-0.5 rounded border border-indigo-100/50",
5797
5998
  "data-testid": `collections-rollup-${key}-${item[collection.value.schema.primaryKey]}`
5798
- }, (0, vue.toDisplayString)((0, vue.unref)(render).rollupDisplay(field, item)), 9, _hoisted_79)) : field.type !== "file" && (0, vue.unref)(isExternalUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5799
- key: 8,
5999
+ }, (0, vue.toDisplayString)((0, vue.unref)(render).rollupDisplay(field, item)), 9, _hoisted_83)) : field.type !== "file" && (0, vue.unref)(isExternalUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
6000
+ key: 9,
5800
6001
  href: String(item[key]),
5801
6002
  target: "_blank",
5802
6003
  rel: "noopener noreferrer",
5803
6004
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5804
6005
  "data-testid": `collections-url-link-${key}-${item[collection.value.schema.primaryKey]}`,
5805
6006
  onClick: _cache[20] || (_cache[20] = (0, vue.withModifiers)(() => {}, ["stop"]))
5806
- }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_80)) : field.type === "file" && (0, vue.unref)(artifactUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5807
- key: 9,
6007
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_84)) : field.type === "file" && (0, vue.unref)(artifactUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
6008
+ key: 10,
5808
6009
  href: (0, vue.unref)(artifactUrl)(item[key]) ?? void 0,
5809
6010
  target: "_blank",
5810
6011
  rel: "noopener noreferrer",
5811
6012
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5812
6013
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5813
6014
  onClick: _cache[21] || (_cache[21] = (0, vue.withModifiers)(() => {}, ["stop"]))
5814
- }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_81)) : field.type === "file" && (0, vue.unref)(fileRoutePath)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5815
- key: 10,
6015
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_85)) : field.type === "file" && (0, vue.unref)(fileRoutePath)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
6016
+ key: 11,
5816
6017
  href: (0, vue.unref)(fileRoutePath)(item[key]) ?? void 0,
5817
6018
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5818
6019
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5819
6020
  onClick: ($event) => (0, vue.unref)(activatePathLink)($event, (0, vue.unref)(fileRoutePath)(item[key]) ?? "", true)
5820
- }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_82)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_83, (0, vue.toDisplayString)((0, vue.unref)(formatCell)(item[key], field.type)), 1))], 64)) : (0, vue.createCommentVNode)("", true)]);
5821
- }), 128))], 42, _hoisted_68);
6021
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_86)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_87, (0, vue.toDisplayString)((0, vue.unref)(formatCell)(item[key], field.type)), 1))], 64)) : (0, vue.createCommentVNode)("", true)]);
6022
+ }), 128))], 42, _hoisted_71);
5822
6023
  }), 128))])])]))]),
5823
6024
  collection.value && (viewing.value || editing.value) && !(calendarActive.value && openDay.value) ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRecordModal_default, {
5824
6025
  key: 4,
@@ -5902,19 +6103,19 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5902
6103
  "data-testid": "collections-chat-modal",
5903
6104
  onClick: (0, vue.withModifiers)(closeChat, ["self"]),
5904
6105
  onKeydown: (0, vue.withKeys)(closeChat, ["esc"])
5905
- }, [(0, vue.createElementVNode)("div", _hoisted_84, [
5906
- (0, vue.createElementVNode)("header", _hoisted_85, [
6106
+ }, [(0, vue.createElementVNode)("div", _hoisted_88, [
6107
+ (0, vue.createElementVNode)("header", _hoisted_89, [
5907
6108
  _cache[55] || (_cache[55] = (0, vue.createElementVNode)("div", { class: "h-9 w-9 flex items-center justify-center rounded-xl bg-indigo-50 text-indigo-600 border border-indigo-100/50" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "forum")], -1)),
5908
- (0, vue.createElementVNode)("div", _hoisted_86, [(0, vue.createElementVNode)("h2", _hoisted_87, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatTitle")), 1), (0, vue.createElementVNode)("span", _hoisted_88, (0, vue.toDisplayString)(collection.value.title), 1)]),
6109
+ (0, vue.createElementVNode)("div", _hoisted_90, [(0, vue.createElementVNode)("h2", _hoisted_91, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatTitle")), 1), (0, vue.createElementVNode)("span", _hoisted_92, (0, vue.toDisplayString)(collection.value.title), 1)]),
5909
6110
  (0, vue.createElementVNode)("button", {
5910
6111
  type: "button",
5911
6112
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-200/50 hover:text-slate-600 transition-colors",
5912
6113
  "aria-label": (0, vue.unref)(t)("common.close"),
5913
6114
  "data-testid": "collections-chat-close",
5914
6115
  onClick: closeChat
5915
- }, [..._cache[54] || (_cache[54] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_89)
6116
+ }, [..._cache[54] || (_cache[54] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_93)
5916
6117
  ]),
5917
- (0, vue.createElementVNode)("div", _hoisted_90, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
6118
+ (0, vue.createElementVNode)("div", _hoisted_94, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
5918
6119
  ref_key: "chatInputEl",
5919
6120
  ref: chatInputEl,
5920
6121
  "onUpdate:modelValue": _cache[26] || (_cache[26] = ($event) => chatMessage.value = $event),
@@ -5923,8 +6124,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5923
6124
  class: "w-full bg-slate-50 border border-slate-200/80 rounded-xl px-3 py-2.5 text-sm placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all resize-none",
5924
6125
  "data-testid": "collections-chat-input",
5925
6126
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["ctrl"]), ["enter"])]
5926
- }, null, 40, _hoisted_91), [[vue.vModelText, chatMessage.value]])]),
5927
- (0, vue.createElementVNode)("footer", _hoisted_92, [(0, vue.createElementVNode)("button", {
6127
+ }, null, 40, _hoisted_95), [[vue.vModelText, chatMessage.value]])]),
6128
+ (0, vue.createElementVNode)("footer", _hoisted_96, [(0, vue.createElementVNode)("button", {
5928
6129
  type: "button",
5929
6130
  class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
5930
6131
  "data-testid": "collections-chat-cancel",
@@ -5935,7 +6136,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5935
6136
  disabled: !chatMessage.value.trim(),
5936
6137
  "data-testid": "collections-chat-send",
5937
6138
  onClick: submitChat
5938
- }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_93)])
6139
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_97)])
5939
6140
  ])], 32)) : (0, vue.createCommentVNode)("", true)
5940
6141
  ]);
5941
6142
  };
@@ -6839,9 +7040,11 @@ exports.collectionUi = collectionUi;
6839
7040
  exports.configureCollectionUi = configureCollectionUi;
6840
7041
  exports.customViewKey = customViewKey;
6841
7042
  exports.plugin = plugin;
7043
+ exports.readCollectionFlagFilters = readCollectionFlagFilters;
6842
7044
  exports.readCollectionSort = readCollectionSort;
6843
7045
  exports.readCollectionViewMode = readCollectionViewMode;
6844
7046
  exports.useCollectionRendering = useCollectionRendering;
7047
+ exports.writeCollectionFlagFilters = writeCollectionFlagFilters;
6845
7048
  exports.writeCollectionSort = writeCollectionSort;
6846
7049
  exports.writeCollectionViewMode = writeCollectionViewMode;
6847
7050