@mulmoclaude/collection-plugin 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vue.js CHANGED
@@ -1,4 +1,4 @@
1
- import { COMPUTED_TYPES, MINUTES_PER_DAY, TOOL_DEFINITION, actionVisible, agentActionRunKey, assignLanes, backlinkRows, boolSortValue, bucketRecords, buildMonthGrid, buildUpdatedRecord, coerceInlineValue, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, draftToRecord, embedTargetId, emptyRow, enumSortValue, errorMessage, executePresentCollection, fieldVisible, firstMissingRequiredField, isSortableField, itemIdOf, itemLabelOf, labelFieldFor, nextSortDirection, numericSortValue, resolveEnumColor, rollupValue, rowFromItem, shortHexId, sortItems, stringSortValue, ymdKey } from "@mulmoclaude/core/collection";
1
+ import { COMPUTED_TYPES, MINUTES_PER_DAY, TOOL_DEFINITION, actionVisible, agentActionRunKey, assignLanes, backlinkRows, boolSortValue, bucketRecords, buildMonthGrid, buildUpdatedRecord, coerceInlineValue, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, draftToRecord, embedTargetId, emptyRow, enumSortValue, errorMessage, executePresentCollection, fieldVisible, firstMissingRequiredField, isSortableField, itemIdOf, itemIsDone, itemLabelOf, labelFieldFor, nextSortDirection, numericSortValue, resolveEnumColor, rollupValue, rowFromItem, shortHexId, sortItems, stringSortValue, ymdKey } from "@mulmoclaude/core/collection";
2
2
  import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, effectScope, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onUnmounted, openBlock, reactive, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useModel, vModelCheckbox, vModelDynamic, vModelSelect, vModelText, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
3
3
  import { createI18n } from "vue-i18n";
4
4
  import draggable from "vuedraggable";
@@ -90,6 +90,11 @@ var i18n = createI18n({
90
90
  searchSummary: "Showing {shown} of {total}",
91
91
  noMatchingItems: "No matching items",
92
92
  clearSearch: "Clear search",
93
+ flagFilterButton: "Filters",
94
+ flagFilterAll: "Filter by {label}",
95
+ flagFilterHide: "Hiding {label}",
96
+ flagFilterOnly: "Only {label}",
97
+ flagDoneChip: "Done",
93
98
  sortBy: "Sort by {field}",
94
99
  openCollection: "Open {title}",
95
100
  createTitle: "Add new",
@@ -233,6 +238,11 @@ var i18n = createI18n({
233
238
  searchSummary: "{total} 件中 {shown} 件を表示",
234
239
  noMatchingItems: "一致する項目がありません",
235
240
  clearSearch: "検索をクリア",
241
+ flagFilterButton: "絞り込み",
242
+ flagFilterAll: "{label} で絞り込む",
243
+ flagFilterHide: "{label} を非表示中",
244
+ flagFilterOnly: "{label} のみ表示中",
245
+ flagDoneChip: "完了",
236
246
  sortBy: "{field}で並べ替え",
237
247
  openCollection: "{title} を開く",
238
248
  createTitle: "新規追加",
@@ -376,6 +386,11 @@ var i18n = createI18n({
376
386
  searchSummary: "显示 {total} 条中的 {shown} 条",
377
387
  noMatchingItems: "没有匹配的项目",
378
388
  clearSearch: "清除搜索",
389
+ flagFilterButton: "筛选",
390
+ flagFilterAll: "按{label}筛选",
391
+ flagFilterHide: "已隐藏{label}",
392
+ flagFilterOnly: "仅显示{label}",
393
+ flagDoneChip: "已完成",
379
394
  sortBy: "按{field}排序",
380
395
  openCollection: "打开 {title}",
381
396
  createTitle: "新增",
@@ -519,6 +534,11 @@ var i18n = createI18n({
519
534
  searchSummary: "{total}개 중 {shown}개 표시",
520
535
  noMatchingItems: "일치하는 항목이 없습니다",
521
536
  clearSearch: "검색 지우기",
537
+ flagFilterButton: "필터",
538
+ flagFilterAll: "{label}(으)로 필터",
539
+ flagFilterHide: "{label} 숨김",
540
+ flagFilterOnly: "{label}만 표시",
541
+ flagDoneChip: "완료",
522
542
  sortBy: "{field} 기준 정렬",
523
543
  openCollection: "{title} 열기",
524
544
  createTitle: "새로 추가",
@@ -662,6 +682,11 @@ var i18n = createI18n({
662
682
  searchSummary: "Mostrando {shown} de {total}",
663
683
  noMatchingItems: "No hay elementos coincidentes",
664
684
  clearSearch: "Borrar búsqueda",
685
+ flagFilterButton: "Filtros",
686
+ flagFilterAll: "Filtrar por {label}",
687
+ flagFilterHide: "Ocultando {label}",
688
+ flagFilterOnly: "Solo {label}",
689
+ flagDoneChip: "Hecho",
665
690
  sortBy: "Ordenar por {field}",
666
691
  openCollection: "Abrir {title}",
667
692
  createTitle: "Añadir nuevo",
@@ -805,6 +830,11 @@ var i18n = createI18n({
805
830
  searchSummary: "Mostrando {shown} de {total}",
806
831
  noMatchingItems: "Nenhum item correspondente",
807
832
  clearSearch: "Limpar busca",
833
+ flagFilterButton: "Filtros",
834
+ flagFilterAll: "Filtrar por {label}",
835
+ flagFilterHide: "Ocultando {label}",
836
+ flagFilterOnly: "Somente {label}",
837
+ flagDoneChip: "Concluído",
808
838
  sortBy: "Ordenar por {field}",
809
839
  openCollection: "Abrir {title}",
810
840
  createTitle: "Adicionar novo",
@@ -948,6 +978,11 @@ var i18n = createI18n({
948
978
  searchSummary: "Affichage de {shown} sur {total}",
949
979
  noMatchingItems: "Aucun élément correspondant",
950
980
  clearSearch: "Effacer la recherche",
981
+ flagFilterButton: "Filtres",
982
+ flagFilterAll: "Filtrer par {label}",
983
+ flagFilterHide: "{label} masqué",
984
+ flagFilterOnly: "Uniquement {label}",
985
+ flagDoneChip: "Terminé",
951
986
  sortBy: "Trier par {field}",
952
987
  openCollection: "Ouvrir {title}",
953
988
  createTitle: "Ajouter",
@@ -1091,6 +1126,11 @@ var i18n = createI18n({
1091
1126
  searchSummary: "{shown} von {total} werden angezeigt",
1092
1127
  noMatchingItems: "Keine passenden Einträge",
1093
1128
  clearSearch: "Suche zurücksetzen",
1129
+ flagFilterButton: "Filter",
1130
+ flagFilterAll: "Nach {label} filtern",
1131
+ flagFilterHide: "{label} ausgeblendet",
1132
+ flagFilterOnly: "Nur {label}",
1133
+ flagDoneChip: "Erledigt",
1094
1134
  sortBy: "Nach {field} sortieren",
1095
1135
  openCollection: "{title} öffnen",
1096
1136
  createTitle: "Neu hinzufügen",
@@ -2571,77 +2611,79 @@ var _hoisted_57$1 = {
2571
2611
  key: 2,
2572
2612
  class: "text-slate-300"
2573
2613
  };
2574
- var _hoisted_58$1 = [
2614
+ var _hoisted_58$1 = ["data-testid"];
2615
+ var _hoisted_59$1 = ["data-testid"];
2616
+ var _hoisted_60$1 = [
2575
2617
  "href",
2576
2618
  "tabindex",
2577
2619
  "data-testid",
2578
2620
  "onClick",
2579
2621
  "onKeydown"
2580
2622
  ];
2581
- var _hoisted_59$1 = {
2582
- key: 3,
2623
+ var _hoisted_61$1 = {
2624
+ key: 4,
2583
2625
  class: "font-semibold text-slate-900 tabular-nums text-sm"
2584
2626
  };
2585
- var _hoisted_60$1 = {
2586
- key: 4,
2627
+ var _hoisted_62$1 = {
2628
+ key: 5,
2587
2629
  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"
2588
2630
  };
2589
- var _hoisted_61$1 = ["data-testid"];
2590
- var _hoisted_62$1 = {
2591
- key: 6,
2631
+ var _hoisted_63$1 = ["data-testid"];
2632
+ var _hoisted_64$1 = {
2633
+ key: 7,
2592
2634
  class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1"
2593
2635
  };
2594
- var _hoisted_63$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2595
- var _hoisted_64$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2596
- var _hoisted_65$1 = { class: "divide-y divide-slate-100" };
2597
- var _hoisted_66$1 = {
2636
+ var _hoisted_65$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2637
+ var _hoisted_66$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2638
+ var _hoisted_67$1 = { class: "divide-y divide-slate-100" };
2639
+ var _hoisted_68$1 = {
2598
2640
  key: 0,
2599
2641
  class: "material-icons text-emerald-600 text-base"
2600
2642
  };
2601
- var _hoisted_67$1 = {
2643
+ var _hoisted_69$1 = {
2602
2644
  key: 1,
2603
2645
  class: "text-slate-300"
2604
2646
  };
2605
- var _hoisted_68$1 = {
2606
- key: 7,
2647
+ var _hoisted_70$1 = {
2648
+ key: 8,
2607
2649
  class: "text-slate-400 italic"
2608
2650
  };
2609
- var _hoisted_69$1 = {
2610
- key: 8,
2651
+ var _hoisted_71$1 = {
2652
+ key: 9,
2611
2653
  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"
2612
2654
  };
2613
- var _hoisted_70$1 = [
2655
+ var _hoisted_72$1 = [
2614
2656
  "src",
2615
2657
  "alt",
2616
2658
  "data-testid"
2617
2659
  ];
2618
- var _hoisted_71$1 = ["href", "data-testid"];
2619
- var _hoisted_72$1 = ["href", "data-testid"];
2620
- var _hoisted_73$1 = [
2660
+ var _hoisted_73$1 = ["href", "data-testid"];
2661
+ var _hoisted_74$1 = ["href", "data-testid"];
2662
+ var _hoisted_75$1 = [
2621
2663
  "href",
2622
2664
  "data-testid",
2623
2665
  "onClick"
2624
2666
  ];
2625
- var _hoisted_74$1 = {
2626
- key: 15,
2667
+ var _hoisted_76$1 = {
2668
+ key: 16,
2627
2669
  class: "text-slate-800 font-semibold"
2628
2670
  };
2629
- var _hoisted_75$1 = {
2671
+ var _hoisted_77$1 = {
2630
2672
  key: 0,
2631
2673
  class: "col-span-full text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl"
2632
2674
  };
2633
- var _hoisted_76$1 = {
2675
+ var _hoisted_78$1 = {
2634
2676
  key: 1,
2635
2677
  class: "mt-5 pt-4 border-t border-slate-200/60",
2636
2678
  "data-testid": "collections-detail-chat"
2637
2679
  };
2638
- var _hoisted_77$1 = {
2680
+ var _hoisted_79$1 = {
2639
2681
  class: "block text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1.5",
2640
2682
  for: "collections-detail-chat-input"
2641
2683
  };
2642
- var _hoisted_78$1 = { class: "flex items-end gap-2" };
2643
- var _hoisted_79$1 = ["placeholder", "onKeydown"];
2644
- var _hoisted_80$1 = ["disabled"];
2684
+ var _hoisted_80$1 = { class: "flex items-end gap-2" };
2685
+ var _hoisted_81$1 = ["placeholder", "onKeydown"];
2686
+ var _hoisted_82$1 = ["disabled"];
2645
2687
  //#endregion
2646
2688
  //#region src/vue/components/CollectionRecordPanel.vue
2647
2689
  var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
@@ -3003,8 +3045,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
3003
3045
  key: 3,
3004
3046
  class: "text-xs font-medium text-slate-700 break-words",
3005
3047
  "data-testid": `collections-detail-value-${key}`
3006
- }, [field.type === "toggle" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? (openBlock(), createElementBlock("span", _hoisted_53$1, [_cache[12] || (_cache[12] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : (openBlock(), createElementBlock("span", _hoisted_54$1, toDisplayString(unref(t)("common.no")), 1))], 64)) : field.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [detailRecord.value[key] === true ? (openBlock(), createElementBlock("span", _hoisted_55$1, [_cache[13] || (_cache[13] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? (openBlock(), createElementBlock("span", _hoisted_56$1, toDisplayString(unref(t)("common.no")), 1)) : (openBlock(), createElementBlock("span", _hoisted_57$1, "—"))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? (openBlock(), createElementBlock("a", {
3007
- key: 2,
3048
+ }, [field.type === "toggle" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? (openBlock(), createElementBlock("span", _hoisted_53$1, [_cache[12] || (_cache[12] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : (openBlock(), createElementBlock("span", _hoisted_54$1, toDisplayString(unref(t)("common.no")), 1))], 64)) : field.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [detailRecord.value[key] === true ? (openBlock(), createElementBlock("span", _hoisted_55$1, [_cache[13] || (_cache[13] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? (openBlock(), createElementBlock("span", _hoisted_56$1, toDisplayString(unref(t)("common.no")), 1)) : (openBlock(), createElementBlock("span", _hoisted_57$1, "—"))], 64)) : field.type === "flag" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [__props.render.deriveRecord(detailRecord.value)[key] === true ? (openBlock(), createElementBlock("span", {
3049
+ key: 0,
3050
+ 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",
3051
+ "data-testid": `collections-detail-flag-${key}`
3052
+ }, [_cache[14] || (_cache[14] = createElementVNode("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), createTextVNode(" " + toDisplayString(unref(t)("common.yes")), 1)], 8, _hoisted_58$1)) : (openBlock(), createElementBlock("span", {
3053
+ key: 1,
3054
+ 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",
3055
+ "data-testid": `collections-detail-flag-${key}`
3056
+ }, toDisplayString(unref(t)("common.no")), 9, _hoisted_59$1))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? (openBlock(), createElementBlock("a", {
3057
+ key: 3,
3008
3058
  href: unref(cui).recordHref?.(field.to, String(detailRecord.value[key])),
3009
3059
  tabindex: unref(cui).recordHref?.(field.to, String(detailRecord.value[key])) ? void 0 : 0,
3010
3060
  role: "link",
@@ -3012,16 +3062,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
3012
3062
  "data-testid": `collections-detail-ref-${key}`,
3013
3063
  onClick: ($event) => unref(activateRefLink)($event, field.to, String(detailRecord.value[key])),
3014
3064
  onKeydown: [withKeys(($event) => unref(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["enter"]), withKeys(($event) => unref(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["space"])]
3015
- }, toDisplayString(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_58$1)) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_59$1, toDisplayString(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_60$1, toDisplayString(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? (openBlock(), createElementBlock("span", {
3016
- key: 5,
3065
+ }, toDisplayString(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_60$1)) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_61$1, toDisplayString(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_62$1, toDisplayString(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? (openBlock(), createElementBlock("span", {
3066
+ key: 6,
3017
3067
  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",
3018
3068
  "data-testid": `collections-detail-rollup-${key}`
3019
- }, toDisplayString(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_61$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? (openBlock(), createElementBlock("div", _hoisted_62$1, [createElementVNode("table", _hoisted_63$1, [createElementVNode("thead", _hoisted_64$1, [createElementVNode("tr", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(field.of, (subField, subKey) => {
3069
+ }, toDisplayString(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_63$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? (openBlock(), createElementBlock("div", _hoisted_64$1, [createElementVNode("table", _hoisted_65$1, [createElementVNode("thead", _hoisted_66$1, [createElementVNode("tr", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(field.of, (subField, subKey) => {
3020
3070
  return openBlock(), createElementBlock("th", {
3021
3071
  key: subKey,
3022
3072
  class: "text-left px-4 py-2 font-bold"
3023
3073
  }, toDisplayString(subField.label), 1);
3024
- }), 128))])]), createElementVNode("tbody", _hoisted_65$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
3074
+ }), 128))])]), createElementVNode("tbody", _hoisted_67$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
3025
3075
  return openBlock(), createElementBlock("tr", {
3026
3076
  key: rowIdx,
3027
3077
  class: "hover:bg-slate-50/50"
@@ -3029,48 +3079,48 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
3029
3079
  return openBlock(), createElementBlock("td", {
3030
3080
  key: subKey,
3031
3081
  class: "px-4 py-2 align-middle font-medium"
3032
- }, [subField.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [row[subKey] === true ? (openBlock(), createElementBlock("span", _hoisted_66$1, "check_circle")) : (openBlock(), createElementBlock("span", _hoisted_67$1, "—"))], 64)) : (openBlock(), createElementBlock("span", {
3082
+ }, [subField.type === "boolean" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [row[subKey] === true ? (openBlock(), createElementBlock("span", _hoisted_68$1, "check_circle")) : (openBlock(), createElementBlock("span", _hoisted_69$1, "—"))], 64)) : (openBlock(), createElementBlock("span", {
3033
3083
  key: 1,
3034
3084
  class: normalizeClass([subField.type === "money" ? "font-bold text-slate-800 tabular-nums" : ""])
3035
3085
  }, toDisplayString(__props.render.formatSubCell(subField, row[subKey], detailRecord.value)), 3))]);
3036
3086
  }), 128))]);
3037
- }), 128))])])])) : field.type === "table" ? (openBlock(), createElementBlock("span", _hoisted_68$1, toDisplayString(unref(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? (openBlock(), createElementBlock("div", _hoisted_69$1, toDisplayString(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? (openBlock(), createBlock(CollectionEmbedView_default, {
3038
- key: 9,
3087
+ }), 128))])])])) : field.type === "table" ? (openBlock(), createElementBlock("span", _hoisted_70$1, toDisplayString(unref(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? (openBlock(), createElementBlock("div", _hoisted_71$1, toDisplayString(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? (openBlock(), createBlock(CollectionEmbedView_default, {
3088
+ key: 10,
3039
3089
  view: embedViews.value[key],
3040
3090
  "field-key": String(key)
3041
3091
  }, null, 8, ["view", "field-key"])) : field.type === "backlinks" && backlinksViews.value[key] ? (openBlock(), createBlock(CollectionBacklinksView_default, {
3042
- key: 10,
3092
+ key: 11,
3043
3093
  view: backlinksViews.value[key],
3044
3094
  "field-key": String(key)
3045
3095
  }, null, 8, ["view", "field-key"])) : field.type === "image" && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? (openBlock(), createElementBlock("img", {
3046
- key: 11,
3096
+ key: 12,
3047
3097
  src: unref(resolveImageSrc)(String(detailRecord.value[key])),
3048
3098
  alt: field.label,
3049
3099
  class: "max-h-64 max-w-full object-contain rounded-lg border border-slate-200 bg-slate-50",
3050
3100
  "data-testid": `collections-detail-image-${key}`
3051
- }, null, 8, _hoisted_70$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
3052
- key: 12,
3101
+ }, null, 8, _hoisted_72$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
3102
+ key: 13,
3053
3103
  href: String(detailRecord.value[key]),
3054
3104
  target: "_blank",
3055
3105
  rel: "noopener noreferrer",
3056
3106
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3057
3107
  "data-testid": `collections-detail-url-${key}`
3058
- }, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_71$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
3059
- key: 13,
3108
+ }, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_73$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
3109
+ key: 14,
3060
3110
  href: __props.render.artifactUrl(detailRecord.value[key]) ?? void 0,
3061
3111
  target: "_blank",
3062
3112
  rel: "noopener noreferrer",
3063
3113
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3064
3114
  "data-testid": `collections-detail-file-${key}`
3065
- }, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_72$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
3066
- key: 14,
3115
+ }, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_74$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? (openBlock(), createElementBlock("a", {
3116
+ key: 15,
3067
3117
  href: __props.render.fileRoutePath(detailRecord.value[key]) ?? void 0,
3068
3118
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3069
3119
  "data-testid": `collections-detail-file-${key}`,
3070
3120
  onClick: ($event) => unref(activatePathLink)($event, __props.render.fileRoutePath(detailRecord.value[key]) ?? "")
3071
- }, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_73$1)) : (openBlock(), createElementBlock("span", _hoisted_74$1, toDisplayString(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : createCommentVNode("", true)], 64);
3072
- }), 128)), editing.value && __props.saveError ? (openBlock(), createElementBlock("p", _hoisted_75$1, toDisplayString(__props.saveError), 1)) : createCommentVNode("", true)]),
3073
- !editing.value ? (openBlock(), createElementBlock("div", _hoisted_76$1, [createElementVNode("label", _hoisted_77$1, toDisplayString(unref(t)("collectionsView.itemChatLabel")), 1), createElementVNode("div", _hoisted_78$1, [withDirectives(createElementVNode("textarea", {
3121
+ }, toDisplayString(String(detailRecord.value[key])), 9, _hoisted_75$1)) : (openBlock(), createElementBlock("span", _hoisted_76$1, toDisplayString(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : createCommentVNode("", true)], 64);
3122
+ }), 128)), editing.value && __props.saveError ? (openBlock(), createElementBlock("p", _hoisted_77$1, toDisplayString(__props.saveError), 1)) : createCommentVNode("", true)]),
3123
+ !editing.value ? (openBlock(), createElementBlock("div", _hoisted_78$1, [createElementVNode("label", _hoisted_79$1, toDisplayString(unref(t)("collectionsView.itemChatLabel")), 1), createElementVNode("div", _hoisted_80$1, [withDirectives(createElementVNode("textarea", {
3074
3124
  id: "collections-detail-chat-input",
3075
3125
  "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => chatMessage.value = $event),
3076
3126
  rows: "2",
@@ -3078,13 +3128,13 @@ var CollectionRecordPanel_default = /* @__PURE__ */ defineComponent({
3078
3128
  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",
3079
3129
  "data-testid": "collections-detail-chat-input",
3080
3130
  onKeydown: [withKeys(withModifiers(submitItemChat, ["meta"]), ["enter"]), withKeys(withModifiers(submitItemChat, ["ctrl"]), ["enter"])]
3081
- }, null, 40, _hoisted_79$1), [[vModelText, chatMessage.value]]), createElementVNode("button", {
3131
+ }, null, 40, _hoisted_81$1), [[vModelText, chatMessage.value]]), createElementVNode("button", {
3082
3132
  type: "button",
3083
3133
  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",
3084
3134
  disabled: !chatMessage.value.trim(),
3085
3135
  "data-testid": "collections-detail-chat-send",
3086
3136
  onClick: submitItemChat
3087
- }, [_cache[14] || (_cache[14] = createElementVNode("span", { class: "material-icons text-sm" }, "forum", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.chat")), 1)], 8, _hoisted_80$1)])])) : createCommentVNode("", true)
3137
+ }, [_cache[15] || (_cache[15] = createElementVNode("span", { class: "material-icons text-sm" }, "forum", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.chat")), 1)], 8, _hoisted_82$1)])])) : createCommentVNode("", true)
3088
3138
  ]),
3089
3139
  _: 1
3090
3140
  }, 40, ["data-testid"]);
@@ -3879,6 +3929,38 @@ function writeCollectionSort(slug, sort) {
3879
3929
  localStorage.setItem(SORT_STORAGE_KEY, JSON.stringify(all));
3880
3930
  } catch {}
3881
3931
  }
3932
+ var FLAG_FILTER_STORAGE_KEY = "collection_flag_filters";
3933
+ function isFlagFilterState(value) {
3934
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
3935
+ return Object.values(value).every((mode) => mode === "hide" || mode === "only");
3936
+ }
3937
+ function readAllFlagFilters() {
3938
+ try {
3939
+ const raw = localStorage.getItem(FLAG_FILTER_STORAGE_KEY);
3940
+ if (!raw) return {};
3941
+ const parsed = JSON.parse(raw);
3942
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
3943
+ const out = {};
3944
+ for (const [slug, value] of Object.entries(parsed)) if (isFlagFilterState(value)) out[slug] = value;
3945
+ return out;
3946
+ } catch {
3947
+ return {};
3948
+ }
3949
+ }
3950
+ /** The slug's persisted chip states ({} when none). A key whose flag no
3951
+ * longer exists in the schema is harmless — the chip list is derived
3952
+ * from the live schema, so a stale entry just never renders/filters. */
3953
+ function readCollectionFlagFilters(slug) {
3954
+ return readAllFlagFilters()[slug] ?? {};
3955
+ }
3956
+ /** Persist the slug's chip states; an empty state clears the entry. */
3957
+ function writeCollectionFlagFilters(slug, filters) {
3958
+ try {
3959
+ const all = Object.fromEntries(Object.entries(readAllFlagFilters()).filter(([key]) => key !== slug));
3960
+ if (Object.keys(filters).length > 0) all[slug] = filters;
3961
+ localStorage.setItem(FLAG_FILTER_STORAGE_KEY, JSON.stringify(all));
3962
+ } catch {}
3963
+ }
3882
3964
  //#endregion
3883
3965
  //#region src/vue/components/CollectionView.vue?vue&type=script&setup=true&lang.ts
3884
3966
  var _hoisted_1$6 = { class: "h-full flex flex-col bg-slate-50/30" };
@@ -3937,186 +4019,201 @@ var _hoisted_21$3 = {
3937
4019
  var _hoisted_22$3 = ["placeholder", "aria-label"];
3938
4020
  var _hoisted_23$2 = ["aria-label"];
3939
4021
  var _hoisted_24$1 = { class: "flex items-center gap-2" };
3940
- var _hoisted_25$1 = ["aria-label"];
3941
- var _hoisted_26$1 = ["aria-pressed"];
3942
- var _hoisted_27$1 = ["aria-pressed"];
3943
- var _hoisted_28 = ["aria-pressed"];
3944
- var _hoisted_29 = [
4022
+ var _hoisted_25$1 = ["aria-label", "aria-expanded"];
4023
+ var _hoisted_26$1 = {
4024
+ key: 0,
4025
+ class: "min-w-4 h-4 px-1 flex items-center justify-center rounded-full bg-indigo-600 text-white text-[10px] font-bold"
4026
+ };
4027
+ var _hoisted_27$1 = ["aria-label"];
4028
+ var _hoisted_28 = [
4029
+ "title",
4030
+ "aria-label",
3945
4031
  "aria-pressed",
3946
4032
  "data-testid",
3947
4033
  "onClick"
3948
4034
  ];
3949
- var _hoisted_30 = { class: "material-icons text-sm" };
3950
- var _hoisted_31 = [
4035
+ var _hoisted_29 = { class: "flex-1 text-left" };
4036
+ var _hoisted_30 = ["aria-label"];
4037
+ var _hoisted_31 = ["aria-pressed"];
4038
+ var _hoisted_32 = ["aria-pressed"];
4039
+ var _hoisted_33 = ["aria-pressed"];
4040
+ var _hoisted_34 = [
4041
+ "aria-pressed",
4042
+ "data-testid",
4043
+ "onClick"
4044
+ ];
4045
+ var _hoisted_35 = { class: "material-icons text-sm" };
4046
+ var _hoisted_36 = [
3951
4047
  "title",
3952
4048
  "aria-label",
3953
4049
  "aria-expanded"
3954
4050
  ];
3955
- var _hoisted_32 = {
4051
+ var _hoisted_37 = {
3956
4052
  key: 0,
3957
4053
  class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
3958
4054
  "data-testid": "collection-view-add-menu"
3959
4055
  };
3960
- var _hoisted_33 = ["title", "aria-label"];
3961
- var _hoisted_34 = ["value", "aria-label"];
3962
- var _hoisted_35 = ["value"];
3963
- var _hoisted_36 = ["value", "aria-label"];
3964
- var _hoisted_37 = ["value"];
3965
- var _hoisted_38 = {
3966
- key: 3,
4056
+ var _hoisted_38 = ["title", "aria-label"];
4057
+ var _hoisted_39 = ["value", "aria-label"];
4058
+ var _hoisted_40 = ["value"];
4059
+ var _hoisted_41 = ["value", "aria-label"];
4060
+ var _hoisted_42 = ["value"];
4061
+ var _hoisted_43 = {
4062
+ key: 4,
3967
4063
  class: "text-[10px] text-slate-400 font-bold uppercase tracking-wider select-none"
3968
4064
  };
3969
- var _hoisted_39 = {
4065
+ var _hoisted_44 = {
3970
4066
  key: 3,
3971
4067
  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",
3972
4068
  "data-testid": "collections-data-issues"
3973
4069
  };
3974
- var _hoisted_40 = { class: "flex-1" };
3975
- var _hoisted_41 = { class: "flex-1 overflow-auto" };
3976
- var _hoisted_42 = {
4070
+ var _hoisted_45 = { class: "flex-1" };
4071
+ var _hoisted_46 = { class: "flex-1 overflow-auto" };
4072
+ var _hoisted_47 = {
3977
4073
  key: 0,
3978
4074
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
3979
4075
  };
3980
- var _hoisted_43 = {
4076
+ var _hoisted_48 = {
3981
4077
  key: 1,
3982
4078
  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"
3983
4079
  };
3984
- var _hoisted_44 = { key: 2 };
3985
- var _hoisted_45 = {
4080
+ var _hoisted_49 = { key: 2 };
4081
+ var _hoisted_50 = {
3986
4082
  key: 3,
3987
4083
  class: "p-4"
3988
4084
  };
3989
- var _hoisted_46 = {
4085
+ var _hoisted_51 = {
3990
4086
  key: 4,
3991
4087
  class: "h-full flex flex-col"
3992
4088
  };
3993
- var _hoisted_47 = {
4089
+ var _hoisted_52 = {
3994
4090
  key: 0,
3995
4091
  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",
3996
4092
  "data-testid": "collections-inline-error"
3997
4093
  };
3998
- var _hoisted_48 = { class: "flex-1" };
3999
- var _hoisted_49 = ["aria-label"];
4000
- var _hoisted_50 = { class: "flex-1 min-h-0 px-3 py-2" };
4001
- var _hoisted_51 = {
4094
+ var _hoisted_53 = { class: "flex-1" };
4095
+ var _hoisted_54 = ["aria-label"];
4096
+ var _hoisted_55 = { class: "flex-1 min-h-0 px-3 py-2" };
4097
+ var _hoisted_56 = {
4002
4098
  key: 5,
4003
4099
  class: "h-full",
4004
4100
  "data-testid": "collection-custom-view-body"
4005
4101
  };
4006
- var _hoisted_52 = {
4102
+ var _hoisted_57 = {
4007
4103
  key: 6,
4008
4104
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
4009
4105
  };
4010
- var _hoisted_53 = { class: "font-semibold text-slate-600" };
4011
- var _hoisted_54 = {
4106
+ var _hoisted_58 = { class: "font-semibold text-slate-600" };
4107
+ var _hoisted_59 = {
4012
4108
  key: 7,
4013
4109
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
4014
4110
  };
4015
- var _hoisted_55 = { class: "font-semibold text-slate-600" };
4016
- var _hoisted_56 = {
4111
+ var _hoisted_60 = { class: "font-semibold text-slate-600" };
4112
+ var _hoisted_61 = {
4017
4113
  key: 8,
4018
4114
  class: "overflow-x-auto [container-type:inline-size]"
4019
4115
  };
4020
- var _hoisted_57 = {
4116
+ var _hoisted_62 = {
4021
4117
  key: 0,
4022
4118
  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",
4023
4119
  "data-testid": "collections-inline-error"
4024
4120
  };
4025
- var _hoisted_58 = { class: "flex-1" };
4026
- var _hoisted_59 = ["aria-label"];
4027
- var _hoisted_60 = { class: "min-w-full text-xs" };
4028
- var _hoisted_61 = { class: "bg-slate-50 border-b border-slate-200" };
4029
- var _hoisted_62 = ["aria-sort"];
4030
- var _hoisted_63 = { class: "flex items-center gap-1" };
4031
- var _hoisted_64 = ["title"];
4032
- var _hoisted_65 = [
4121
+ var _hoisted_63 = { class: "flex-1" };
4122
+ var _hoisted_64 = ["aria-label"];
4123
+ var _hoisted_65 = { class: "min-w-full text-xs" };
4124
+ var _hoisted_66 = { class: "bg-slate-50 border-b border-slate-200" };
4125
+ var _hoisted_67 = ["aria-sort"];
4126
+ var _hoisted_68 = { class: "flex items-center gap-1" };
4127
+ var _hoisted_69 = ["title"];
4128
+ var _hoisted_70 = [
4033
4129
  "data-testid",
4034
4130
  "aria-label",
4035
4131
  "onClick",
4036
4132
  "onPointerenter"
4037
4133
  ];
4038
- var _hoisted_66 = { class: "material-icons text-base align-middle" };
4039
- var _hoisted_67 = { class: "divide-y divide-slate-100 bg-white" };
4040
- var _hoisted_68 = [
4134
+ var _hoisted_71 = { class: "material-icons text-base align-middle" };
4135
+ var _hoisted_72 = { class: "divide-y divide-slate-100 bg-white" };
4136
+ var _hoisted_73 = [
4041
4137
  "aria-label",
4042
4138
  "data-testid",
4043
4139
  "onClick",
4044
4140
  "onKeydown"
4045
4141
  ];
4046
- var _hoisted_69 = [
4142
+ var _hoisted_74 = [
4047
4143
  "checked",
4048
4144
  "disabled",
4049
4145
  "data-testid",
4050
4146
  "aria-label",
4051
4147
  "onChange"
4052
4148
  ];
4053
- var _hoisted_70 = [
4149
+ var _hoisted_75 = [
4054
4150
  "checked",
4055
4151
  "disabled",
4056
4152
  "data-testid",
4057
4153
  "aria-label",
4058
4154
  "onChange"
4059
4155
  ];
4060
- var _hoisted_71 = {
4061
- key: 2,
4156
+ var _hoisted_76 = ["data-testid", "aria-label"];
4157
+ var _hoisted_77 = {
4158
+ key: 3,
4062
4159
  class: "block truncate"
4063
4160
  };
4064
- var _hoisted_72 = [
4161
+ var _hoisted_78 = [
4065
4162
  "href",
4066
4163
  "tabindex",
4067
4164
  "data-testid",
4068
4165
  "onClick",
4069
4166
  "onKeydown"
4070
4167
  ];
4071
- var _hoisted_73 = [
4168
+ var _hoisted_79 = [
4072
4169
  "value",
4073
4170
  "disabled",
4074
4171
  "data-testid",
4075
4172
  "aria-label",
4076
4173
  "onChange"
4077
4174
  ];
4078
- var _hoisted_74 = {
4175
+ var _hoisted_80 = {
4079
4176
  key: 0,
4080
4177
  value: ""
4081
4178
  };
4082
- var _hoisted_75 = ["value"];
4083
- var _hoisted_76 = {
4084
- key: 4,
4179
+ var _hoisted_81 = ["value"];
4180
+ var _hoisted_82 = {
4181
+ key: 5,
4085
4182
  class: "block truncate tabular-nums font-semibold text-slate-900"
4086
4183
  };
4087
- var _hoisted_77 = {
4088
- key: 5,
4184
+ var _hoisted_83 = {
4185
+ key: 6,
4089
4186
  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"
4090
4187
  };
4091
- var _hoisted_78 = {
4092
- key: 6,
4188
+ var _hoisted_84 = {
4189
+ key: 7,
4093
4190
  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"
4094
4191
  };
4095
- var _hoisted_79 = ["data-testid"];
4096
- var _hoisted_80 = ["href", "data-testid"];
4097
- var _hoisted_81 = ["href", "data-testid"];
4098
- var _hoisted_82 = [
4192
+ var _hoisted_85 = ["data-testid"];
4193
+ var _hoisted_86 = ["href", "data-testid"];
4194
+ var _hoisted_87 = ["href", "data-testid"];
4195
+ var _hoisted_88 = [
4099
4196
  "href",
4100
4197
  "data-testid",
4101
4198
  "onClick"
4102
4199
  ];
4103
- var _hoisted_83 = {
4104
- key: 11,
4200
+ var _hoisted_89 = {
4201
+ key: 12,
4105
4202
  class: "block truncate text-slate-600"
4106
4203
  };
4107
- var _hoisted_84 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4108
- var _hoisted_85 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4109
- var _hoisted_86 = { class: "flex-1" };
4110
- var _hoisted_87 = {
4204
+ var _hoisted_90 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4205
+ var _hoisted_91 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4206
+ var _hoisted_92 = { class: "flex-1" };
4207
+ var _hoisted_93 = {
4111
4208
  id: "collections-chat-title",
4112
4209
  class: "text-sm font-bold text-slate-800 uppercase tracking-wide"
4113
4210
  };
4114
- var _hoisted_88 = { class: "text-xs text-slate-400 font-semibold" };
4115
- var _hoisted_89 = ["aria-label"];
4116
- var _hoisted_90 = { class: "px-6 py-5" };
4117
- var _hoisted_91 = ["placeholder", "onKeydown"];
4118
- 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" };
4119
- var _hoisted_93 = ["disabled"];
4211
+ var _hoisted_94 = { class: "text-xs text-slate-400 font-semibold" };
4212
+ var _hoisted_95 = ["aria-label"];
4213
+ var _hoisted_96 = { class: "px-6 py-5" };
4214
+ var _hoisted_97 = ["placeholder", "onKeydown"];
4215
+ var _hoisted_98 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
4216
+ var _hoisted_99 = ["disabled"];
4120
4217
  /** `slug` / `selected` are supplied only in EMBEDDED mode (the
4121
4218
  * `presentCollection` chat card mounts this component and drives both
4122
4219
  * from the tool result). In standalone route mode (the
@@ -4127,6 +4224,11 @@ var _hoisted_93 = ["disabled"];
4127
4224
  * is our "rendered inside a chat" signal. When set, chat-triggering
4128
4225
  * actions send into the current session instead of spawning a new
4129
4226
  * chat (see `runAction` / `submitChat`). */
4227
+ var COMPLETION_CHIP_KEY = "__completion";
4228
+ /** The field types that earn a filter-menu entry: declared predicates
4229
+ * (`flag`) plus the fields that ARE a predicate already — a stored
4230
+ * `boolean` and a `toggle`'s projected on/off state. Enums stay out:
4231
+ * they need a value picker, and kanban already slices by enum. */
4130
4232
  var LIVE_REFRESH_DEBOUNCE_MS = 150;
4131
4233
  //#endregion
4132
4234
  //#region src/vue/components/CollectionView.vue
@@ -4253,6 +4355,125 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
4253
4355
  if (!query) return items.value;
4254
4356
  return items.value.filter((item) => itemMatchesQuery(item, query));
4255
4357
  });
4358
+ /** Chip key (state/testid/localStorage) for the synthesized
4359
+ * legacy-completion chip. Field names are unrestricted strings, so a
4360
+ * schema COULD declare a field with this exact name — the chip list
4361
+ * below skips synthesizing in that case, and the predicate dispatch
4362
+ * keys off the structural `synthetic` marker, never this string. */
4363
+ function storedFlagFiltersFor(slug) {
4364
+ return slug ? readCollectionFlagFilters(slug) : {};
4365
+ }
4366
+ const flagFilters = ref(storedFlagFiltersFor(activeSlug.value));
4367
+ const CHIP_FIELD_TYPES = /* @__PURE__ */ new Set([
4368
+ "flag",
4369
+ "boolean",
4370
+ "toggle"
4371
+ ]);
4372
+ /** True when an existing FIELD chip already expresses the legacy
4373
+ * completion predicate exactly, so a synthesized "done" chip would be a
4374
+ * duplicate: a boolean `completionField` (done ⇔ `"true"` ⇔ the
4375
+ * boolean's own chip), or a `toggle` projecting the `completionField`
4376
+ * whose `onValue` is the single done value (the todos-schema shape:
4377
+ * toggle "Done" on `status` + `completionDoneValues: ["done"]`). A
4378
+ * superset pair (extra done values) still synthesizes — no field chip
4379
+ * covers it. */
4380
+ function completionCoveredByFieldChip(schema) {
4381
+ const { completionField, completionDoneValues } = schema;
4382
+ if (completionDoneValues?.length !== 1) return false;
4383
+ const [doneValue] = completionDoneValues;
4384
+ if (schema.fields[completionField ?? ""]?.type === "boolean") return doneValue === "true";
4385
+ return Object.values(schema.fields).some((field) => field.type === "toggle" && field.field === completionField && field.onValue === doneValue);
4386
+ }
4387
+ const flagChips = computed(() => {
4388
+ const schema = collection.value?.schema;
4389
+ if (!schema) return [];
4390
+ const chips = Object.entries(schema.fields).filter(([, field]) => CHIP_FIELD_TYPES.has(field.type)).map(([key, field]) => ({
4391
+ key,
4392
+ label: field.label ?? key
4393
+ }));
4394
+ if (schema.completionField && schema.completionDoneValues && schema.fields[schema.completionField]?.type !== "flag" && !completionCoveredByFieldChip(schema) && schema.fields[COMPLETION_CHIP_KEY] === void 0) chips.push({
4395
+ key: COMPLETION_CHIP_KEY,
4396
+ label: t("collectionsView.flagDoneChip"),
4397
+ synthetic: true
4398
+ });
4399
+ return chips;
4400
+ });
4401
+ /** Own-property read of a chip's active mode. Field names may shadow
4402
+ * `Object.prototype` members (`toString`, `valueOf`, …) — a plain
4403
+ * `filters[key]` on such a key reads the inherited function, which
4404
+ * renders as an "active" chip that can never cycle (Codex review on
4405
+ * PR #2176). Every chip-state read goes through here. */
4406
+ function flagFilterMode(key) {
4407
+ const filters = flagFilters.value;
4408
+ return Object.hasOwn(filters, key) ? filters[key] : void 0;
4409
+ }
4410
+ /** A flag FIELD's computed boolean for one row (list cells + sort):
4411
+ * the enriched record's value, so a flag over derived/rollup inputs
4412
+ * reads correctly. */
4413
+ function flagValueOf(key, item) {
4414
+ return render.deriveRecord(item)[key] === true;
4415
+ }
4416
+ /** The chip's boolean for one row — `itemIsDone` for the synthesized
4417
+ * completion chip, the stored/projected value for `boolean`/`toggle`
4418
+ * fields, the computed flag value otherwise. */
4419
+ function chipMatches(chip, item) {
4420
+ const schema = collection.value?.schema;
4421
+ if (!schema) return false;
4422
+ if (chip.synthetic) return itemIsDone(schema, item);
4423
+ const field = schema.fields[chip.key];
4424
+ if (field?.type === "toggle") return toggleChecked(item, field);
4425
+ if (field?.type === "boolean") return item[chip.key] === true;
4426
+ return flagValueOf(chip.key, item);
4427
+ }
4428
+ /** `filteredItems` further narrowed by every ACTIVE chip (AND). Consumed
4429
+ * only by the table (sortedItems / count summary / empty state). */
4430
+ const tableFilteredItems = computed(() => {
4431
+ const active = flagChips.value.filter((chip) => flagFilterMode(chip.key) !== void 0);
4432
+ if (active.length === 0) return filteredItems.value;
4433
+ return filteredItems.value.filter((item) => active.every((chip) => chipMatches(chip, item) === (flagFilterMode(chip.key) === "only")));
4434
+ });
4435
+ /** Cycle a chip all → hide → only → all. */
4436
+ function cycleFlagFilter(key) {
4437
+ const current = flagFilterMode(key);
4438
+ const next = current === void 0 ? "hide" : current === "hide" ? "only" : void 0;
4439
+ const rest = Object.fromEntries(Object.entries(flagFilters.value).filter(([entry]) => entry !== key));
4440
+ flagFilters.value = next ? {
4441
+ ...rest,
4442
+ [key]: next
4443
+ } : rest;
4444
+ }
4445
+ function flagChipIcon(key) {
4446
+ return flagFilterMode(key) === "only" ? "check_box" : "check_box_outline_blank";
4447
+ }
4448
+ function flagChipIconClass(key) {
4449
+ const mode = flagFilterMode(key);
4450
+ if (mode === "hide") return "text-slate-600";
4451
+ if (mode === "only") return "text-indigo-600";
4452
+ return "text-slate-300";
4453
+ }
4454
+ function flagChipClass(key) {
4455
+ const mode = flagFilterMode(key);
4456
+ if (mode === "hide") return "bg-slate-100 text-slate-700";
4457
+ if (mode === "only") return "bg-indigo-50 text-indigo-700";
4458
+ return "text-slate-500";
4459
+ }
4460
+ /** How many chips currently filter (badge on the menu trigger). */
4461
+ const activeFlagFilterCount = computed(() => flagChips.value.filter((chip) => flagFilterMode(chip.key) !== void 0).length);
4462
+ const filterMenuOpen = ref(false);
4463
+ const filterMenuRef = ref(null);
4464
+ function closeFilterMenuOnOutsideClick(event) {
4465
+ if (!filterMenuRef.value?.contains(event.target)) filterMenuOpen.value = false;
4466
+ }
4467
+ watch(filterMenuOpen, (open) => {
4468
+ if (open) document.addEventListener("mousedown", closeFilterMenuOnOutsideClick);
4469
+ else document.removeEventListener("mousedown", closeFilterMenuOnOutsideClick);
4470
+ });
4471
+ function flagChipTitle(chip) {
4472
+ const mode = flagFilterMode(chip.key);
4473
+ if (mode === "hide") return t("collectionsView.flagFilterHide", { label: chip.label });
4474
+ if (mode === "only") return t("collectionsView.flagFilterOnly", { label: chip.label });
4475
+ return t("collectionsView.flagFilterAll", { label: chip.label });
4476
+ }
4256
4477
  function storedSortFor(slug) {
4257
4478
  return slug && readCollectionSort(slug) || null;
4258
4479
  }
@@ -4299,10 +4520,11 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
4299
4520
  default: return stringSortValue(raw);
4300
4521
  }
4301
4522
  }
4302
- /** Comparable value for one row under the active field. Toggle and derived
4303
- * need the whole record; every other type keys off the raw cell. */
4523
+ /** Comparable value for one row under the active field. Toggle, flag, and
4524
+ * derived need the whole record; every other type keys off the raw cell. */
4304
4525
  function sortValueOf(field, key, item) {
4305
4526
  if (field.type === "toggle") return boolSortValue(toggleChecked(item, field));
4527
+ if (field.type === "flag") return boolSortValue(flagValueOf(key, item));
4306
4528
  if (field.type === "derived") return derivedSortValue(field, key, item);
4307
4529
  return scalarSortValue(field, item[key]);
4308
4530
  }
@@ -4318,8 +4540,8 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
4318
4540
  const sortedItems = computed(() => {
4319
4541
  const state = sortState.value;
4320
4542
  const field = state ? collection.value?.schema.fields[state.field] : void 0;
4321
- if (!state || !field) return filteredItems.value;
4322
- return sortItems(filteredItems.value, state.direction, (item) => sortValueOf(field, state.field, item));
4543
+ if (!state || !field) return tableFilteredItems.value;
4544
+ return sortItems(tableFilteredItems.value, state.direction, (item) => sortValueOf(field, state.field, item));
4323
4545
  });
4324
4546
  /** Stringified primary-key value for a row (the row's stable identity). */
4325
4547
  function rowId(item) {
@@ -5264,7 +5486,9 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5264
5486
  anchorOverride.value = null;
5265
5487
  kanbanOverride.value = null;
5266
5488
  addMenuOpen.value = false;
5489
+ filterMenuOpen.value = false;
5267
5490
  sortState.value = storedSortFor(slug);
5491
+ flagFilters.value = storedFlagFiltersFor(slug);
5268
5492
  }
5269
5493
  if (slug) loadCollection(slug);
5270
5494
  else {
@@ -5313,12 +5537,14 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5313
5537
  clearLiveRefreshTimer();
5314
5538
  if (refreshNoteTimer !== void 0) clearTimeout(refreshNoteTimer);
5315
5539
  document.removeEventListener("mousedown", closeAddMenuOnOutsideClick);
5540
+ document.removeEventListener("mousedown", closeFilterMenuOnOutsideClick);
5316
5541
  });
5317
5542
  watch([
5318
5543
  activeView,
5319
5544
  calendarAnchorField,
5320
5545
  kanbanGroupField,
5321
5546
  sortState,
5547
+ flagFilters,
5322
5548
  loading
5323
5549
  ], () => {
5324
5550
  if (embedded.value) emit("viewStateChange", {
@@ -5329,6 +5555,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5329
5555
  if (activeSlug.value && !loading.value && collection.value) {
5330
5556
  if (!embedded.value) writeCollectionViewMode(activeSlug.value, activeView.value);
5331
5557
  writeCollectionSort(activeSlug.value, sortState.value);
5558
+ writeCollectionFlagFilters(activeSlug.value, flagFilters.value);
5332
5559
  }
5333
5560
  });
5334
5561
  watch(activeSelected, () => {
@@ -5347,9 +5574,9 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5347
5574
  "aria-label": unref(t)("collectionsView.backToIndex"),
5348
5575
  "data-testid": "collections-back",
5349
5576
  onClick: goBack
5350
- }, [..._cache[27] || (_cache[27] = [createElementVNode("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : createCommentVNode("", true),
5577
+ }, [..._cache[28] || (_cache[28] = [createElementVNode("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : createCommentVNode("", true),
5351
5578
  collection.value ? (openBlock(), createElementBlock("div", _hoisted_4$5, [createElementVNode("span", _hoisted_5$5, toDisplayString(collection.value.icon), 1)])) : createCommentVNode("", true),
5352
- createElementVNode("div", _hoisted_6$4, [createElementVNode("h1", _hoisted_7$4, toDisplayString(collection.value?.title ?? unref(t)("collectionsView.title")), 1), collection.value ? (openBlock(), createElementBlock("span", _hoisted_8$4, [createTextVNode(toDisplayString(collection.value.slug) + " ", 1), isReadOnly.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_9$4, [_cache[28] || (_cache[28] = createElementVNode("span", { class: "material-icons text-[11px]" }, "lock", -1)), createTextVNode(" " + toDisplayString(unref(t)("collectionsView.readonlyChip")), 1)]), dataSourceRoute.value ? (openBlock(), createElementBlock("a", {
5579
+ createElementVNode("div", _hoisted_6$4, [createElementVNode("h1", _hoisted_7$4, toDisplayString(collection.value?.title ?? unref(t)("collectionsView.title")), 1), collection.value ? (openBlock(), createElementBlock("span", _hoisted_8$4, [createTextVNode(toDisplayString(collection.value.slug) + " ", 1), isReadOnly.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_9$4, [_cache[29] || (_cache[29] = createElementVNode("span", { class: "material-icons text-[11px]" }, "lock", -1)), createTextVNode(" " + toDisplayString(unref(t)("collectionsView.readonlyChip")), 1)]), dataSourceRoute.value ? (openBlock(), createElementBlock("a", {
5353
5580
  key: 0,
5354
5581
  href: dataSourceRoute.value ?? void 0,
5355
5582
  class: "ml-1 normal-case tracking-normal font-mono font-normal text-slate-500 hover:text-indigo-700 hover:underline",
@@ -5382,7 +5609,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5382
5609
  class: "h-8 px-2.5 flex items-center gap-1 rounded border border-indigo-200 bg-white hover:bg-indigo-50 text-indigo-600 font-bold text-xs transition-colors",
5383
5610
  "data-testid": "collections-chat",
5384
5611
  onClick: openChat
5385
- }, [_cache[29] || (_cache[29] = createElementVNode("span", { class: "material-icons text-sm" }, "forum", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.chat")), 1)])) : createCommentVNode("", true),
5612
+ }, [_cache[30] || (_cache[30] = createElementVNode("span", { class: "material-icons text-sm" }, "forum", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.chat")), 1)])) : createCommentVNode("", true),
5386
5613
  (openBlock(true), createElementBlock(Fragment, null, renderList(collectionActions.value, (action) => {
5387
5614
  return openBlock(), createElementBlock("button", {
5388
5615
  key: action.id,
@@ -5399,7 +5626,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5399
5626
  class: "h-8 px-2.5 flex items-center gap-1 rounded bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs transition-colors shadow-sm",
5400
5627
  "data-testid": "collections-add-item",
5401
5628
  onClick: openCreate
5402
- }, [_cache[30] || (_cache[30] = createElementVNode("span", { class: "material-icons text-sm" }, "add", -1)), createElementVNode("span", null, toDisplayString(unref(t)("common.add")), 1)])) : createCommentVNode("", true),
5629
+ }, [_cache[31] || (_cache[31] = createElementVNode("span", { class: "material-icons text-sm" }, "add", -1)), createElementVNode("span", null, toDisplayString(unref(t)("common.add")), 1)])) : createCommentVNode("", true),
5403
5630
  canDeleteCollection.value && !embedded.value ? (openBlock(), createElementBlock("button", {
5404
5631
  key: 6,
5405
5632
  type: "button",
@@ -5408,7 +5635,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5408
5635
  "aria-label": unref(t)("collectionsView.deleteCollection"),
5409
5636
  "data-testid": "collections-delete",
5410
5637
  onClick: confirmCollectionDelete
5411
- }, [..._cache[31] || (_cache[31] = [createElementVNode("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_16$4)) : createCommentVNode("", true),
5638
+ }, [..._cache[32] || (_cache[32] = [createElementVNode("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_16$4)) : createCommentVNode("", true),
5412
5639
  canDeleteFeed.value && !embedded.value ? (openBlock(), createElementBlock("button", {
5413
5640
  key: 7,
5414
5641
  type: "button",
@@ -5417,11 +5644,11 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5417
5644
  "aria-label": unref(t)("collectionsView.deleteFeed"),
5418
5645
  "data-testid": "feeds-delete",
5419
5646
  onClick: confirmFeedDelete
5420
- }, [..._cache[32] || (_cache[32] = [createElementVNode("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_17$4)) : createCommentVNode("", true)
5647
+ }, [..._cache[33] || (_cache[33] = [createElementVNode("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_17$4)) : createCommentVNode("", true)
5421
5648
  ])) : createCommentVNode("", true),
5422
- refreshNote.value ? (openBlock(), createElementBlock("div", _hoisted_18$4, [_cache[33] || (_cache[33] = createElementVNode("span", { class: "material-icons text-base text-indigo-600" }, "hourglass_top", -1)), createElementVNode("span", _hoisted_19$3, toDisplayString(refreshNote.value), 1)])) : createCommentVNode("", true),
5649
+ refreshNote.value ? (openBlock(), createElementBlock("div", _hoisted_18$4, [_cache[34] || (_cache[34] = createElementVNode("span", { class: "material-icons text-base text-indigo-600" }, "hourglass_top", -1)), createElementVNode("span", _hoisted_19$3, toDisplayString(refreshNote.value), 1)])) : createCommentVNode("", true),
5423
5650
  collection.value && (!__props.hideSearch && items.value.length > 0 || !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value)) ? (openBlock(), createElementBlock("div", _hoisted_20$3, [!__props.hideSearch && items.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_21$3, [
5424
- _cache[35] || (_cache[35] = createElementVNode("span", { class: "absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none" }, [createElementVNode("span", { class: "material-icons text-lg" }, "search")], -1)),
5651
+ _cache[36] || (_cache[36] = createElementVNode("span", { class: "absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none" }, [createElementVNode("span", { class: "material-icons text-lg" }, "search")], -1)),
5425
5652
  withDirectives(createElementVNode("input", {
5426
5653
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
5427
5654
  type: "text",
@@ -5435,10 +5662,50 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5435
5662
  "aria-label": unref(t)("collectionsView.clearSearch"),
5436
5663
  class: "absolute inset-y-0 right-0 flex items-center pr-2.5 text-slate-400 hover:text-slate-600",
5437
5664
  onClick: _cache[2] || (_cache[2] = ($event) => searchQuery.value = "")
5438
- }, [..._cache[34] || (_cache[34] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_23$2)) : createCommentVNode("", true)
5665
+ }, [..._cache[35] || (_cache[35] = [createElementVNode("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_23$2)) : createCommentVNode("", true)
5439
5666
  ])) : createCommentVNode("", true), createElementVNode("div", _hoisted_24$1, [
5440
- !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? (openBlock(), createElementBlock("div", {
5667
+ activeView.value === "table" && flagChips.value.length > 0 && items.value.length > 0 ? (openBlock(), createElementBlock("div", {
5441
5668
  key: 0,
5669
+ ref_key: "filterMenuRef",
5670
+ ref: filterMenuRef,
5671
+ class: "relative"
5672
+ }, [createElementVNode("button", {
5673
+ type: "button",
5674
+ class: normalizeClass(["h-8 px-2.5 flex items-center gap-1 rounded-full text-xs font-medium transition-colors", activeFlagFilterCount.value > 0 ? "bg-indigo-50 text-indigo-700 border border-indigo-300" : "bg-transparent text-slate-500 border border-dashed border-slate-300 hover:bg-slate-50"]),
5675
+ "aria-label": unref(t)("collectionsView.flagFilterButton"),
5676
+ "aria-expanded": filterMenuOpen.value,
5677
+ "data-testid": "collections-filter-menu",
5678
+ onClick: _cache[3] || (_cache[3] = ($event) => filterMenuOpen.value = !filterMenuOpen.value)
5679
+ }, [
5680
+ _cache[37] || (_cache[37] = createElementVNode("span", {
5681
+ class: "material-icons text-sm",
5682
+ "aria-hidden": "true"
5683
+ }, "filter_alt", -1)),
5684
+ createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.flagFilterButton")), 1),
5685
+ activeFlagFilterCount.value > 0 ? (openBlock(), createElementBlock("span", _hoisted_26$1, toDisplayString(activeFlagFilterCount.value), 1)) : createCommentVNode("", true)
5686
+ ], 10, _hoisted_25$1), filterMenuOpen.value ? (openBlock(), createElementBlock("div", {
5687
+ key: 0,
5688
+ class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
5689
+ role: "group",
5690
+ "aria-label": unref(t)("collectionsView.flagFilterButton"),
5691
+ "data-testid": "collections-filter-menu-panel"
5692
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(flagChips.value, (chip) => {
5693
+ return openBlock(), createElementBlock("button", {
5694
+ key: chip.key,
5695
+ type: "button",
5696
+ class: normalizeClass(["w-full h-8 px-3 flex items-center gap-2 text-xs font-medium transition-colors hover:bg-slate-50", flagChipClass(chip.key)]),
5697
+ title: flagChipTitle(chip),
5698
+ "aria-label": flagChipTitle(chip),
5699
+ "aria-pressed": flagFilterMode(chip.key) !== void 0,
5700
+ "data-testid": `collections-flag-chip-${chip.key}`,
5701
+ onClick: ($event) => cycleFlagFilter(chip.key)
5702
+ }, [createElementVNode("span", {
5703
+ class: normalizeClass(["material-icons text-sm", flagChipIconClass(chip.key)]),
5704
+ "aria-hidden": "true"
5705
+ }, toDisplayString(flagChipIcon(chip.key)), 3), createElementVNode("span", _hoisted_29, toDisplayString(chip.label), 1)], 10, _hoisted_28);
5706
+ }), 128))], 8, _hoisted_27$1)) : createCommentVNode("", true)], 512)) : createCommentVNode("", true),
5707
+ !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? (openBlock(), createElementBlock("div", {
5708
+ key: 1,
5442
5709
  class: "flex gap-0.5",
5443
5710
  role: "group",
5444
5711
  "aria-label": unref(t)("collectionsView.viewToggle")
@@ -5448,24 +5715,24 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5448
5715
  class: normalizeClass(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", activeView.value === "table" ? "bg-indigo-600 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"]),
5449
5716
  "aria-pressed": activeView.value === "table",
5450
5717
  "data-testid": "collection-view-toggle-table",
5451
- onClick: _cache[3] || (_cache[3] = ($event) => setView("table"))
5452
- }, [_cache[36] || (_cache[36] = createElementVNode("span", { class: "material-icons text-sm" }, "table_rows", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewTable")), 1)], 10, _hoisted_26$1),
5718
+ onClick: _cache[4] || (_cache[4] = ($event) => setView("table"))
5719
+ }, [_cache[38] || (_cache[38] = createElementVNode("span", { class: "material-icons text-sm" }, "table_rows", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewTable")), 1)], 10, _hoisted_31),
5453
5720
  hasCalendar.value ? (openBlock(), createElementBlock("button", {
5454
5721
  key: 0,
5455
5722
  type: "button",
5456
5723
  class: normalizeClass(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", activeView.value === "calendar" ? "bg-indigo-600 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"]),
5457
5724
  "aria-pressed": activeView.value === "calendar",
5458
5725
  "data-testid": "collection-view-toggle-calendar",
5459
- onClick: _cache[4] || (_cache[4] = ($event) => setView("calendar"))
5460
- }, [_cache[37] || (_cache[37] = createElementVNode("span", { class: "material-icons text-sm" }, "calendar_month", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_27$1)) : createCommentVNode("", true),
5726
+ onClick: _cache[5] || (_cache[5] = ($event) => setView("calendar"))
5727
+ }, [_cache[39] || (_cache[39] = createElementVNode("span", { class: "material-icons text-sm" }, "calendar_month", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_32)) : createCommentVNode("", true),
5461
5728
  hasKanban.value ? (openBlock(), createElementBlock("button", {
5462
5729
  key: 1,
5463
5730
  type: "button",
5464
5731
  class: normalizeClass(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", activeView.value === "kanban" ? "bg-indigo-600 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"]),
5465
5732
  "aria-pressed": activeView.value === "kanban",
5466
5733
  "data-testid": "collection-view-toggle-kanban",
5467
- onClick: _cache[5] || (_cache[5] = ($event) => setView("kanban"))
5468
- }, [_cache[38] || (_cache[38] = createElementVNode("span", { class: "material-icons text-sm" }, "view_kanban", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_28)) : createCommentVNode("", true),
5734
+ onClick: _cache[6] || (_cache[6] = ($event) => setView("kanban"))
5735
+ }, [_cache[40] || (_cache[40] = createElementVNode("span", { class: "material-icons text-sm" }, "view_kanban", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_33)) : createCommentVNode("", true),
5469
5736
  (openBlock(true), createElementBlock(Fragment, null, renderList(customViews.value, (cv) => {
5470
5737
  return openBlock(), createElementBlock("button", {
5471
5738
  key: cv.id,
@@ -5474,7 +5741,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5474
5741
  "aria-pressed": activeView.value === unref(customViewKey)(cv.id),
5475
5742
  "data-testid": `collection-view-custom-${cv.id}`,
5476
5743
  onClick: ($event) => setCustomView(cv.id)
5477
- }, [createElementVNode("span", _hoisted_30, toDisplayString(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), createElementVNode("span", null, toDisplayString(cv.label), 1)], 10, _hoisted_29);
5744
+ }, [createElementVNode("span", _hoisted_35, toDisplayString(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), createElementVNode("span", null, toDisplayString(cv.label), 1)], 10, _hoisted_34);
5478
5745
  }), 128)),
5479
5746
  canAddCustomView.value ? (openBlock(), createElementBlock("div", {
5480
5747
  key: 2,
@@ -5489,17 +5756,17 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5489
5756
  "aria-expanded": addMenuOpen.value,
5490
5757
  "data-testid": "collection-view-add",
5491
5758
  onClick: onAddViewClick
5492
- }, [..._cache[39] || (_cache[39] = [createElementVNode("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_31), addMenuOpen.value ? (openBlock(), createElementBlock("div", _hoisted_32, [createElementVNode("button", {
5759
+ }, [..._cache[41] || (_cache[41] = [createElementVNode("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_36), addMenuOpen.value ? (openBlock(), createElementBlock("div", _hoisted_37, [createElementVNode("button", {
5493
5760
  type: "button",
5494
5761
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5495
5762
  "data-testid": "collection-view-add-desktop",
5496
- onClick: _cache[6] || (_cache[6] = ($event) => addCustomView("desktop"))
5497
- }, [_cache[40] || (_cache[40] = createElementVNode("span", { class: "material-icons text-sm" }, "dashboard_customize", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.addViewDesktop")), 1)]), createElementVNode("button", {
5763
+ onClick: _cache[7] || (_cache[7] = ($event) => addCustomView("desktop"))
5764
+ }, [_cache[42] || (_cache[42] = createElementVNode("span", { class: "material-icons text-sm" }, "dashboard_customize", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.addViewDesktop")), 1)]), createElementVNode("button", {
5498
5765
  type: "button",
5499
5766
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5500
5767
  "data-testid": "collection-view-add-mobile",
5501
- onClick: _cache[7] || (_cache[7] = ($event) => addCustomView("mobile"))
5502
- }, [_cache[41] || (_cache[41] = createElementVNode("span", { class: "material-icons text-sm" }, "smartphone", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.addViewMobile")), 1)])])) : createCommentVNode("", true)], 512)) : createCommentVNode("", true),
5768
+ onClick: _cache[8] || (_cache[8] = ($event) => addCustomView("mobile"))
5769
+ }, [_cache[43] || (_cache[43] = createElementVNode("span", { class: "material-icons text-sm" }, "smartphone", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.addViewMobile")), 1)])])) : createCommentVNode("", true)], 512)) : createCommentVNode("", true),
5503
5770
  canConfigureViews.value ? (openBlock(), createElementBlock("button", {
5504
5771
  key: 3,
5505
5772
  type: "button",
@@ -5507,51 +5774,51 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5507
5774
  title: unref(t)("collectionsView.config.open"),
5508
5775
  "aria-label": unref(t)("collectionsView.config.open"),
5509
5776
  "data-testid": "collection-config-open",
5510
- onClick: _cache[8] || (_cache[8] = ($event) => configOpen.value = true)
5511
- }, [..._cache[42] || (_cache[42] = [createElementVNode("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_33)) : createCommentVNode("", true)
5512
- ], 8, _hoisted_25$1)) : createCommentVNode("", true),
5777
+ onClick: _cache[9] || (_cache[9] = ($event) => configOpen.value = true)
5778
+ }, [..._cache[44] || (_cache[44] = [createElementVNode("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_38)) : createCommentVNode("", true)
5779
+ ], 8, _hoisted_30)) : createCommentVNode("", true),
5513
5780
  calendarActive.value && dateFields.value.length > 1 ? (openBlock(), createElementBlock("select", {
5514
- key: 1,
5781
+ key: 2,
5515
5782
  value: calendarAnchorField.value,
5516
5783
  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",
5517
5784
  "aria-label": unref(t)("collectionsView.calendarFieldLabel"),
5518
5785
  "data-testid": "collection-calendar-field",
5519
- onChange: _cache[9] || (_cache[9] = ($event) => anchorOverride.value = $event.target.value)
5786
+ onChange: _cache[10] || (_cache[10] = ($event) => anchorOverride.value = $event.target.value)
5520
5787
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(dateFields.value, (key) => {
5521
5788
  return openBlock(), createElementBlock("option", {
5522
5789
  key,
5523
5790
  value: key
5524
- }, toDisplayString(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_35);
5525
- }), 128))], 40, _hoisted_34)) : createCommentVNode("", true),
5791
+ }, toDisplayString(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_40);
5792
+ }), 128))], 40, _hoisted_39)) : createCommentVNode("", true),
5526
5793
  kanbanActive.value && enumFields.value.length > 1 ? (openBlock(), createElementBlock("select", {
5527
- key: 2,
5794
+ key: 3,
5528
5795
  value: kanbanGroupField.value,
5529
5796
  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",
5530
5797
  "aria-label": unref(t)("collectionsView.kanbanFieldLabel"),
5531
5798
  "data-testid": "collection-kanban-field",
5532
- onChange: _cache[10] || (_cache[10] = ($event) => kanbanOverride.value = $event.target.value)
5799
+ onChange: _cache[11] || (_cache[11] = ($event) => kanbanOverride.value = $event.target.value)
5533
5800
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(enumFields.value, (key) => {
5534
5801
  return openBlock(), createElementBlock("option", {
5535
5802
  key,
5536
5803
  value: key
5537
- }, toDisplayString(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_37);
5538
- }), 128))], 40, _hoisted_36)) : createCommentVNode("", true),
5539
- items.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_38, toDisplayString(unref(t)("collectionsView.searchSummary", {
5540
- shown: filteredItems.value.length,
5804
+ }, toDisplayString(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_42);
5805
+ }), 128))], 40, _hoisted_41)) : createCommentVNode("", true),
5806
+ items.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_43, toDisplayString(unref(t)("collectionsView.searchSummary", {
5807
+ shown: activeView.value === "table" ? tableFilteredItems.value.length : filteredItems.value.length,
5541
5808
  total: items.value.length
5542
5809
  })), 1)) : createCommentVNode("", true)
5543
5810
  ])])) : createCommentVNode("", true),
5544
- collection.value && dataIssues.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_39, [
5545
- _cache[44] || (_cache[44] = createElementVNode("span", { class: "material-icons text-amber-600" }, "warning", -1)),
5546
- createElementVNode("span", _hoisted_40, toDisplayString(unref(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5811
+ collection.value && dataIssues.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_44, [
5812
+ _cache[46] || (_cache[46] = createElementVNode("span", { class: "material-icons text-amber-600" }, "warning", -1)),
5813
+ createElementVNode("span", _hoisted_45, toDisplayString(unref(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5547
5814
  createElementVNode("button", {
5548
5815
  type: "button",
5549
5816
  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",
5550
5817
  "data-testid": "collections-repair",
5551
5818
  onClick: repairCollection
5552
- }, [_cache[43] || (_cache[43] = createElementVNode("span", { class: "material-icons text-sm" }, "build", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.repair")), 1)])
5819
+ }, [_cache[45] || (_cache[45] = createElementVNode("span", { class: "material-icons text-sm" }, "build", -1)), createElementVNode("span", null, toDisplayString(unref(t)("collectionsView.repair")), 1)])
5553
5820
  ])) : createCommentVNode("", true),
5554
- createElementVNode("div", _hoisted_41, [loading.value ? (openBlock(), createElementBlock("div", _hoisted_42, [_cache[45] || (_cache[45] = createElementVNode("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), createElementVNode("span", null, toDisplayString(unref(t)("common.loading")), 1)])) : loadError.value ? (openBlock(), createElementBlock("div", _hoisted_43, [_cache[46] || (_cache[46] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)), createElementVNode("span", null, toDisplayString(loadError.value === "not-found" ? unref(t)("collectionsView.notFound") : `${unref(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? (openBlock(), createElementBlock("div", _hoisted_44)) : calendarActive.value ? (openBlock(), createElementBlock("div", _hoisted_45, [createVNode(CollectionCalendarView_default, {
5821
+ createElementVNode("div", _hoisted_46, [loading.value ? (openBlock(), createElementBlock("div", _hoisted_47, [_cache[47] || (_cache[47] = createElementVNode("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), createElementVNode("span", null, toDisplayString(unref(t)("common.loading")), 1)])) : loadError.value ? (openBlock(), createElementBlock("div", _hoisted_48, [_cache[48] || (_cache[48] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)), createElementVNode("span", null, toDisplayString(loadError.value === "not-found" ? unref(t)("collectionsView.notFound") : `${unref(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? (openBlock(), createElementBlock("div", _hoisted_49)) : calendarActive.value ? (openBlock(), createElementBlock("div", _hoisted_50, [createVNode(CollectionCalendarView_default, {
5555
5822
  schema: collection.value.schema,
5556
5823
  items: filteredItems.value,
5557
5824
  "anchor-field": calendarAnchorField.value,
@@ -5587,7 +5854,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5587
5854
  }, {
5588
5855
  detail: withCtx(() => [createVNode(CollectionRecordPanel_default, {
5589
5856
  editing: editing.value,
5590
- "onUpdate:editing": _cache[11] || (_cache[11] = ($event) => editing.value = $event),
5857
+ "onUpdate:editing": _cache[12] || (_cache[12] = ($event) => editing.value = $event),
5591
5858
  collection: collection.value,
5592
5859
  viewing: viewing.value,
5593
5860
  saving: saving.value,
@@ -5607,7 +5874,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5607
5874
  onCancel: cancelEditor,
5608
5875
  onEdit: editFromView,
5609
5876
  onClose: onDayClose,
5610
- onDelete: _cache[12] || (_cache[12] = ($event) => viewing.value && confirmDelete(viewing.value)),
5877
+ onDelete: _cache[13] || (_cache[13] = ($event) => viewing.value && confirmDelete(viewing.value)),
5611
5878
  onRunAction: runAction,
5612
5879
  onItemChat
5613
5880
  }, null, 8, [
@@ -5640,16 +5907,16 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5640
5907
  "selected",
5641
5908
  "can-create",
5642
5909
  "show-detail"
5643
- ])) : createCommentVNode("", true)])) : kanbanActive.value ? (openBlock(), createElementBlock("div", _hoisted_46, [inlineError.value ? (openBlock(), createElementBlock("div", _hoisted_47, [
5644
- _cache[48] || (_cache[48] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)),
5645
- createElementVNode("span", _hoisted_48, toDisplayString(unref(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5910
+ ])) : createCommentVNode("", true)])) : kanbanActive.value ? (openBlock(), createElementBlock("div", _hoisted_51, [inlineError.value ? (openBlock(), createElementBlock("div", _hoisted_52, [
5911
+ _cache[50] || (_cache[50] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)),
5912
+ createElementVNode("span", _hoisted_53, toDisplayString(unref(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5646
5913
  createElementVNode("button", {
5647
5914
  type: "button",
5648
5915
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5649
5916
  "aria-label": unref(t)("common.close"),
5650
- onClick: _cache[13] || (_cache[13] = ($event) => inlineError.value = null)
5651
- }, [..._cache[47] || (_cache[47] = [createElementVNode("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_49)
5652
- ])) : createCommentVNode("", true), createElementVNode("div", _hoisted_50, [createVNode(CollectionKanbanView_default, {
5917
+ onClick: _cache[14] || (_cache[14] = ($event) => inlineError.value = null)
5918
+ }, [..._cache[49] || (_cache[49] = [createElementVNode("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_54)
5919
+ ])) : createCommentVNode("", true), createElementVNode("div", _hoisted_55, [createVNode(CollectionKanbanView_default, {
5653
5920
  schema: collection.value.schema,
5654
5921
  items: filteredItems.value,
5655
5922
  "group-field": kanbanGroupField.value,
@@ -5665,7 +5932,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5665
5932
  "selected",
5666
5933
  "notified",
5667
5934
  "readonly"
5668
- ])])])) : activeCustomView.value ? (openBlock(), createElementBlock("div", _hoisted_51, [activeCustomView.value.target === "mobile" ? (openBlock(), createBlock(CollectionRemoteViewPreview_default, {
5935
+ ])])])) : activeCustomView.value ? (openBlock(), createElementBlock("div", _hoisted_56, [activeCustomView.value.target === "mobile" ? (openBlock(), createBlock(CollectionRemoteViewPreview_default, {
5669
5936
  key: 0,
5670
5937
  slug: collection.value.slug,
5671
5938
  view: activeCustomView.value,
@@ -5676,32 +5943,32 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5676
5943
  view: activeCustomView.value,
5677
5944
  onOpenItem: onCustomViewOpenItem,
5678
5945
  onStartChat: onCustomViewStartChat
5679
- }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_52, [_cache[49] || (_cache[49] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), createElementVNode("p", _hoisted_53, toDisplayString(unref(t)(isReadOnly.value ? "collectionsView.itemsEmptyReadonly" : "collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_54, [
5680
- _cache[50] || (_cache[50] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
5681
- createElementVNode("p", _hoisted_55, toDisplayString(unref(t)("collectionsView.noMatchingItems")), 1),
5946
+ }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_57, [_cache[51] || (_cache[51] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), createElementVNode("p", _hoisted_58, toDisplayString(unref(t)(isReadOnly.value ? "collectionsView.itemsEmptyReadonly" : "collectionsView.itemsEmpty")), 1)])) : tableFilteredItems.value.length === 0 && editing.value?.mode !== "create" ? (openBlock(), createElementBlock("div", _hoisted_59, [
5947
+ _cache[52] || (_cache[52] = createElementVNode("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
5948
+ createElementVNode("p", _hoisted_60, toDisplayString(unref(t)("collectionsView.noMatchingItems")), 1),
5682
5949
  createElementVNode("button", {
5683
5950
  type: "button",
5684
5951
  class: "text-xs text-indigo-600 font-semibold hover:underline",
5685
- onClick: _cache[14] || (_cache[14] = ($event) => searchQuery.value = "")
5952
+ onClick: _cache[15] || (_cache[15] = ($event) => (searchQuery.value = "", flagFilters.value = {}))
5686
5953
  }, toDisplayString(unref(t)("collectionsView.clearSearch")), 1)
5687
- ])) : (openBlock(), createElementBlock("div", _hoisted_56, [inlineError.value ? (openBlock(), createElementBlock("div", _hoisted_57, [
5688
- _cache[52] || (_cache[52] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)),
5689
- createElementVNode("span", _hoisted_58, toDisplayString(unref(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5954
+ ])) : (openBlock(), createElementBlock("div", _hoisted_61, [inlineError.value ? (openBlock(), createElementBlock("div", _hoisted_62, [
5955
+ _cache[54] || (_cache[54] = createElementVNode("span", { class: "material-icons text-red-600" }, "error", -1)),
5956
+ createElementVNode("span", _hoisted_63, toDisplayString(unref(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5690
5957
  createElementVNode("button", {
5691
5958
  type: "button",
5692
5959
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5693
5960
  "aria-label": unref(t)("common.close"),
5694
- onClick: _cache[15] || (_cache[15] = ($event) => inlineError.value = null)
5695
- }, [..._cache[51] || (_cache[51] = [createElementVNode("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_59)
5696
- ])) : createCommentVNode("", true), createElementVNode("table", _hoisted_60, [createElementVNode("thead", null, [createElementVNode("tr", _hoisted_61, [(openBlock(true), createElementBlock(Fragment, null, renderList(listColumnFields.value, ([key, field]) => {
5961
+ onClick: _cache[16] || (_cache[16] = ($event) => inlineError.value = null)
5962
+ }, [..._cache[53] || (_cache[53] = [createElementVNode("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_64)
5963
+ ])) : createCommentVNode("", true), createElementVNode("table", _hoisted_65, [createElementVNode("thead", null, [createElementVNode("tr", _hoisted_66, [(openBlock(true), createElementBlock(Fragment, null, renderList(listColumnFields.value, ([key, field]) => {
5697
5964
  return openBlock(), createElementBlock("th", {
5698
5965
  key,
5699
5966
  "aria-sort": unref(isSortableField)(field) ? sortAriaValue(key) : void 0,
5700
5967
  class: "px-5 py-3 font-bold text-slate-500 text-left uppercase tracking-wider whitespace-nowrap"
5701
- }, [createElementVNode("div", _hoisted_63, [createElementVNode("span", {
5968
+ }, [createElementVNode("div", _hoisted_68, [createElementVNode("span", {
5702
5969
  class: "truncate max-w-[14rem]",
5703
5970
  title: field.label
5704
- }, toDisplayString(field.label), 9, _hoisted_64), unref(isSortableField)(field) ? (openBlock(), createElementBlock("button", {
5971
+ }, toDisplayString(field.label), 9, _hoisted_69), unref(isSortableField)(field) ? (openBlock(), createElementBlock("button", {
5705
5972
  key: 0,
5706
5973
  type: "button",
5707
5974
  class: normalizeClass(["inline-flex items-center justify-center rounded p-0.5 -my-1 leading-none transition-colors", sortButtonClass(key)]),
@@ -5709,9 +5976,9 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5709
5976
  "aria-label": unref(t)("collectionsView.sortBy", { field: field.label }),
5710
5977
  onClick: withModifiers(($event) => cycleSort(key), ["stop"]),
5711
5978
  onPointerenter: ($event) => hoveredSortKey.value = key,
5712
- onPointerleave: _cache[16] || (_cache[16] = ($event) => hoveredSortKey.value = null)
5713
- }, [createElementVNode("span", _hoisted_66, toDisplayString(sortIconName(key)), 1)], 42, _hoisted_65)) : createCommentVNode("", true)])], 8, _hoisted_62);
5714
- }), 128))])]), createElementVNode("tbody", _hoisted_67, [(openBlock(true), createElementBlock(Fragment, null, renderList(sortedItems.value, (item) => {
5979
+ onPointerleave: _cache[17] || (_cache[17] = ($event) => hoveredSortKey.value = null)
5980
+ }, [createElementVNode("span", _hoisted_71, toDisplayString(sortIconName(key)), 1)], 42, _hoisted_70)) : createCommentVNode("", true)])], 8, _hoisted_67);
5981
+ }), 128))])]), createElementVNode("tbody", _hoisted_72, [(openBlock(true), createElementBlock(Fragment, null, renderList(sortedItems.value, (item) => {
5715
5982
  return openBlock(), createElementBlock("tr", {
5716
5983
  key: String(item[collection.value.schema.primaryKey] ?? ""),
5717
5984
  class: 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" : ""]),
@@ -5733,9 +6000,9 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5733
6000
  class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer align-middle disabled:opacity-50 disabled:cursor-not-allowed",
5734
6001
  "data-testid": `collections-inline-toggle-${key}-${item[collection.value.schema.primaryKey]}`,
5735
6002
  "aria-label": field.label,
5736
- onClick: _cache[17] || (_cache[17] = withModifiers(() => {}, ["stop"])),
6003
+ onClick: _cache[18] || (_cache[18] = withModifiers(() => {}, ["stop"])),
5737
6004
  onChange: ($event) => commitToggle(item, field)
5738
- }, null, 40, _hoisted_69)) : field.type === "boolean" ? (openBlock(), createElementBlock("input", {
6005
+ }, null, 40, _hoisted_74)) : field.type === "boolean" ? (openBlock(), createElementBlock("input", {
5739
6006
  key: 1,
5740
6007
  type: "checkbox",
5741
6008
  checked: item[key] === true,
@@ -5743,9 +6010,15 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5743
6010
  class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer align-middle disabled:opacity-50 disabled:cursor-not-allowed",
5744
6011
  "data-testid": `collections-inline-bool-${key}-${item[collection.value.schema.primaryKey]}`,
5745
6012
  "aria-label": field.label,
5746
- onClick: _cache[18] || (_cache[18] = withModifiers(() => {}, ["stop"])),
6013
+ onClick: _cache[19] || (_cache[19] = withModifiers(() => {}, ["stop"])),
5747
6014
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.checked)
5748
- }, null, 40, _hoisted_70)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? (openBlock(), createElementBlock("span", _hoisted_71, [createElementVNode("a", {
6015
+ }, null, 40, _hoisted_75)) : field.type === "flag" ? (openBlock(), createElementBlock("span", {
6016
+ key: 2,
6017
+ class: normalizeClass(["material-icons text-lg align-middle", flagValueOf(String(key), item) ? "text-emerald-600" : "text-slate-300"]),
6018
+ "data-testid": `collections-flag-${key}-${item[collection.value.schema.primaryKey]}`,
6019
+ "aria-label": `${field.label}: ${unref(t)(flagValueOf(String(key), item) ? "common.yes" : "common.no")}`,
6020
+ role: "img"
6021
+ }, toDisplayString(flagValueOf(String(key), item) ? "check_circle" : "radio_button_unchecked"), 11, _hoisted_76)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? (openBlock(), createElementBlock("span", _hoisted_77, [createElementVNode("a", {
5749
6022
  href: unref(cui).recordHref?.(field.to, String(item[key])),
5750
6023
  tabindex: unref(cui).recordHref?.(field.to, String(item[key])) ? void 0 : 0,
5751
6024
  role: "link",
@@ -5753,48 +6026,48 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5753
6026
  "data-testid": `collections-ref-link-${key}-${item[key]}`,
5754
6027
  onClick: ($event) => unref(activateRefLink)($event, field.to, String(item[key]), true),
5755
6028
  onKeydown: [withKeys(($event) => unref(activateRefLink)($event, field.to, String(item[key]), true), ["enter"]), withKeys(($event) => unref(activateRefLink)($event, field.to, String(item[key]), true), ["space"])]
5756
- }, toDisplayString(unref(refDisplay)(field.to, String(item[key]))), 41, _hoisted_72)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (openBlock(), createElementBlock("select", {
5757
- key: 3,
6029
+ }, toDisplayString(unref(refDisplay)(field.to, String(item[key]))), 41, _hoisted_78)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (openBlock(), createElementBlock("select", {
6030
+ key: 4,
5758
6031
  value: item[key] == null ? "" : String(item[key]),
5759
6032
  disabled: isReadOnly.value || isRowInlineSaving(item),
5760
6033
  class: 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])]),
5761
6034
  "data-testid": `collections-inline-enum-${key}-${item[collection.value.schema.primaryKey]}`,
5762
6035
  "aria-label": field.label,
5763
- onClick: _cache[19] || (_cache[19] = withModifiers(() => {}, ["stop"])),
6036
+ onClick: _cache[20] || (_cache[20] = withModifiers(() => {}, ["stop"])),
5764
6037
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.value)
5765
- }, [showEnumPlaceholder(item, String(key)) ? (openBlock(), createElementBlock("option", _hoisted_74, toDisplayString(unref(t)("collectionsView.selectPlaceholder")), 1)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(field.values, (value) => {
6038
+ }, [showEnumPlaceholder(item, String(key)) ? (openBlock(), createElementBlock("option", _hoisted_80, toDisplayString(unref(t)("collectionsView.selectPlaceholder")), 1)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(field.values, (value) => {
5766
6039
  return openBlock(), createElementBlock("option", {
5767
6040
  key: value,
5768
6041
  value
5769
- }, toDisplayString(value), 9, _hoisted_75);
5770
- }), 128))], 42, _hoisted_73)) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_76, toDisplayString(unref(formatMoney)(item[key], unref(resolveCurrency)(field, item), unref(locale))), 1)) : field.type === "table" ? (openBlock(), createElementBlock("span", _hoisted_77, [_cache[53] || (_cache[53] = createElementVNode("span", { class: "material-icons text-[11px]" }, "list", -1)), createElementVNode("span", null, toDisplayString(tableSummary(item[key])), 1)])) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_78, toDisplayString(unref(derivedDisplay)(field, unref(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? (openBlock(), createElementBlock("span", {
5771
- key: 7,
6042
+ }, toDisplayString(value), 9, _hoisted_81);
6043
+ }), 128))], 42, _hoisted_79)) : field.type === "money" ? (openBlock(), createElementBlock("span", _hoisted_82, toDisplayString(unref(formatMoney)(item[key], unref(resolveCurrency)(field, item), unref(locale))), 1)) : field.type === "table" ? (openBlock(), createElementBlock("span", _hoisted_83, [_cache[55] || (_cache[55] = createElementVNode("span", { class: "material-icons text-[11px]" }, "list", -1)), createElementVNode("span", null, toDisplayString(tableSummary(item[key])), 1)])) : field.type === "derived" ? (openBlock(), createElementBlock("span", _hoisted_84, toDisplayString(unref(derivedDisplay)(field, unref(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? (openBlock(), createElementBlock("span", {
6044
+ key: 8,
5772
6045
  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",
5773
6046
  "data-testid": `collections-rollup-${key}-${item[collection.value.schema.primaryKey]}`
5774
- }, toDisplayString(unref(render).rollupDisplay(field, item)), 9, _hoisted_79)) : field.type !== "file" && unref(isExternalUrl)(item[key]) ? (openBlock(), createElementBlock("a", {
5775
- key: 8,
6047
+ }, toDisplayString(unref(render).rollupDisplay(field, item)), 9, _hoisted_85)) : field.type !== "file" && unref(isExternalUrl)(item[key]) ? (openBlock(), createElementBlock("a", {
6048
+ key: 9,
5776
6049
  href: String(item[key]),
5777
6050
  target: "_blank",
5778
6051
  rel: "noopener noreferrer",
5779
6052
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5780
6053
  "data-testid": `collections-url-link-${key}-${item[collection.value.schema.primaryKey]}`,
5781
- onClick: _cache[20] || (_cache[20] = withModifiers(() => {}, ["stop"]))
5782
- }, toDisplayString(String(item[key])), 9, _hoisted_80)) : field.type === "file" && unref(artifactUrl)(item[key]) ? (openBlock(), createElementBlock("a", {
5783
- key: 9,
6054
+ onClick: _cache[21] || (_cache[21] = withModifiers(() => {}, ["stop"]))
6055
+ }, toDisplayString(String(item[key])), 9, _hoisted_86)) : field.type === "file" && unref(artifactUrl)(item[key]) ? (openBlock(), createElementBlock("a", {
6056
+ key: 10,
5784
6057
  href: unref(artifactUrl)(item[key]) ?? void 0,
5785
6058
  target: "_blank",
5786
6059
  rel: "noopener noreferrer",
5787
6060
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5788
6061
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5789
- onClick: _cache[21] || (_cache[21] = withModifiers(() => {}, ["stop"]))
5790
- }, toDisplayString(String(item[key])), 9, _hoisted_81)) : field.type === "file" && unref(fileRoutePath)(item[key]) ? (openBlock(), createElementBlock("a", {
5791
- key: 10,
6062
+ onClick: _cache[22] || (_cache[22] = withModifiers(() => {}, ["stop"]))
6063
+ }, toDisplayString(String(item[key])), 9, _hoisted_87)) : field.type === "file" && unref(fileRoutePath)(item[key]) ? (openBlock(), createElementBlock("a", {
6064
+ key: 11,
5792
6065
  href: unref(fileRoutePath)(item[key]) ?? void 0,
5793
6066
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5794
6067
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5795
6068
  onClick: ($event) => unref(activatePathLink)($event, unref(fileRoutePath)(item[key]) ?? "", true)
5796
- }, toDisplayString(String(item[key])), 9, _hoisted_82)) : (openBlock(), createElementBlock("span", _hoisted_83, toDisplayString(unref(formatCell)(item[key], field.type)), 1))], 64)) : createCommentVNode("", true)]);
5797
- }), 128))], 42, _hoisted_68);
6069
+ }, toDisplayString(String(item[key])), 9, _hoisted_88)) : (openBlock(), createElementBlock("span", _hoisted_89, toDisplayString(unref(formatCell)(item[key], field.type)), 1))], 64)) : createCommentVNode("", true)]);
6070
+ }), 128))], 42, _hoisted_73);
5798
6071
  }), 128))])])]))]),
5799
6072
  collection.value && (viewing.value || editing.value) && !(calendarActive.value && openDay.value) ? (openBlock(), createBlock(CollectionRecordModal_default, {
5800
6073
  key: 4,
@@ -5802,7 +6075,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5802
6075
  }, {
5803
6076
  default: withCtx(() => [createVNode(CollectionRecordPanel_default, {
5804
6077
  editing: editing.value,
5805
- "onUpdate:editing": _cache[22] || (_cache[22] = ($event) => editing.value = $event),
6078
+ "onUpdate:editing": _cache[23] || (_cache[23] = ($event) => editing.value = $event),
5806
6079
  collection: collection.value,
5807
6080
  viewing: viewing.value,
5808
6081
  saving: saving.value,
@@ -5822,7 +6095,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5822
6095
  onCancel: cancelEditor,
5823
6096
  onEdit: editFromView,
5824
6097
  onClose: closeView,
5825
- onDelete: _cache[23] || (_cache[23] = ($event) => viewing.value && confirmDelete(viewing.value)),
6098
+ onDelete: _cache[24] || (_cache[24] = ($event) => viewing.value && confirmDelete(viewing.value)),
5826
6099
  onRunAction: runAction,
5827
6100
  onItemChat
5828
6101
  }, null, 8, [
@@ -5850,7 +6123,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5850
6123
  action: mutateModal.value.action,
5851
6124
  pending: mutatePending.value,
5852
6125
  error: mutateError.value,
5853
- onClose: _cache[24] || (_cache[24] = ($event) => mutateModal.value = null),
6126
+ onClose: _cache[25] || (_cache[25] = ($event) => mutateModal.value = null),
5854
6127
  onSubmit: submitMutateParams
5855
6128
  }, null, 8, [
5856
6129
  "action",
@@ -5863,7 +6136,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5863
6136
  title: collection.value.title,
5864
6137
  views: customViews.value,
5865
6138
  onChanged: onViewsChanged,
5866
- onClose: _cache[25] || (_cache[25] = ($event) => configOpen.value = false)
6139
+ onClose: _cache[26] || (_cache[26] = ($event) => configOpen.value = false)
5867
6140
  }, null, 8, [
5868
6141
  "slug",
5869
6142
  "title",
@@ -5878,29 +6151,29 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5878
6151
  "data-testid": "collections-chat-modal",
5879
6152
  onClick: withModifiers(closeChat, ["self"]),
5880
6153
  onKeydown: withKeys(closeChat, ["esc"])
5881
- }, [createElementVNode("div", _hoisted_84, [
5882
- createElementVNode("header", _hoisted_85, [
5883
- _cache[55] || (_cache[55] = 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" }, [createElementVNode("span", { class: "material-icons text-lg" }, "forum")], -1)),
5884
- createElementVNode("div", _hoisted_86, [createElementVNode("h2", _hoisted_87, toDisplayString(unref(t)("collectionsView.chatTitle")), 1), createElementVNode("span", _hoisted_88, toDisplayString(collection.value.title), 1)]),
6154
+ }, [createElementVNode("div", _hoisted_90, [
6155
+ createElementVNode("header", _hoisted_91, [
6156
+ _cache[57] || (_cache[57] = 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" }, [createElementVNode("span", { class: "material-icons text-lg" }, "forum")], -1)),
6157
+ createElementVNode("div", _hoisted_92, [createElementVNode("h2", _hoisted_93, toDisplayString(unref(t)("collectionsView.chatTitle")), 1), createElementVNode("span", _hoisted_94, toDisplayString(collection.value.title), 1)]),
5885
6158
  createElementVNode("button", {
5886
6159
  type: "button",
5887
6160
  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",
5888
6161
  "aria-label": unref(t)("common.close"),
5889
6162
  "data-testid": "collections-chat-close",
5890
6163
  onClick: closeChat
5891
- }, [..._cache[54] || (_cache[54] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_89)
6164
+ }, [..._cache[56] || (_cache[56] = [createElementVNode("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_95)
5892
6165
  ]),
5893
- createElementVNode("div", _hoisted_90, [withDirectives(createElementVNode("textarea", {
6166
+ createElementVNode("div", _hoisted_96, [withDirectives(createElementVNode("textarea", {
5894
6167
  ref_key: "chatInputEl",
5895
6168
  ref: chatInputEl,
5896
- "onUpdate:modelValue": _cache[26] || (_cache[26] = ($event) => chatMessage.value = $event),
6169
+ "onUpdate:modelValue": _cache[27] || (_cache[27] = ($event) => chatMessage.value = $event),
5897
6170
  rows: "4",
5898
6171
  placeholder: unref(t)("collectionsView.chatPlaceholder"),
5899
6172
  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",
5900
6173
  "data-testid": "collections-chat-input",
5901
6174
  onKeydown: [withKeys(withModifiers(submitChat, ["meta"]), ["enter"]), withKeys(withModifiers(submitChat, ["ctrl"]), ["enter"])]
5902
- }, null, 40, _hoisted_91), [[vModelText, chatMessage.value]])]),
5903
- createElementVNode("footer", _hoisted_92, [createElementVNode("button", {
6175
+ }, null, 40, _hoisted_97), [[vModelText, chatMessage.value]])]),
6176
+ createElementVNode("footer", _hoisted_98, [createElementVNode("button", {
5904
6177
  type: "button",
5905
6178
  class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
5906
6179
  "data-testid": "collections-chat-cancel",
@@ -5911,7 +6184,7 @@ var CollectionView_default = /* @__PURE__ */ defineComponent({
5911
6184
  disabled: !chatMessage.value.trim(),
5912
6185
  "data-testid": "collections-chat-send",
5913
6186
  onClick: submitChat
5914
- }, toDisplayString(unref(t)("collectionsView.chatStart")), 9, _hoisted_93)])
6187
+ }, toDisplayString(unref(t)("collectionsView.chatStart")), 9, _hoisted_99)])
5915
6188
  ])], 32)) : createCommentVNode("", true)
5916
6189
  ]);
5917
6190
  };
@@ -6797,6 +7070,6 @@ var plugin = {
6797
7070
  previewComponent: Preview_default
6798
7071
  };
6799
7072
  //#endregion
6800
- export { CollectionCalendarView_default as CollectionCalendarView, CollectionCustomView_default as CollectionCustomView, CollectionDayView_default as CollectionDayView, CollectionEmbedView_default as CollectionEmbedView, CollectionKanbanView_default as CollectionKanbanView, CollectionRecordModal_default as CollectionRecordModal, CollectionRecordPanel_default as CollectionRecordPanel, CollectionView_default as CollectionView, CollectionViewConfigModal_default as CollectionViewConfigModal, CollectionsIndexView_default as CollectionsIndexView, FeedsView_default as FeedsView, Preview_default as PresentCollectionPreview, View_default as PresentCollectionView, applicableViewModes, collectionUi, configureCollectionUi, customViewKey, plugin, readCollectionSort, readCollectionViewMode, useCollectionRendering, writeCollectionSort, writeCollectionViewMode };
7073
+ export { CollectionCalendarView_default as CollectionCalendarView, CollectionCustomView_default as CollectionCustomView, CollectionDayView_default as CollectionDayView, CollectionEmbedView_default as CollectionEmbedView, CollectionKanbanView_default as CollectionKanbanView, CollectionRecordModal_default as CollectionRecordModal, CollectionRecordPanel_default as CollectionRecordPanel, CollectionView_default as CollectionView, CollectionViewConfigModal_default as CollectionViewConfigModal, CollectionsIndexView_default as CollectionsIndexView, FeedsView_default as FeedsView, Preview_default as PresentCollectionPreview, View_default as PresentCollectionView, applicableViewModes, collectionUi, configureCollectionUi, customViewKey, plugin, readCollectionFlagFilters, readCollectionSort, readCollectionViewMode, useCollectionRendering, writeCollectionFlagFilters, writeCollectionSort, writeCollectionViewMode };
6801
7074
 
6802
7075
  //# sourceMappingURL=vue.js.map