@sparklingopinions/sparkling-ui 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +1 -1
  2. package/dist/aliases.d.ts +176 -26
  3. package/dist/components/Avatar/Avatar.js.map +1 -1
  4. package/dist/components/Avatar/Avatar.vue.d.ts +3 -2
  5. package/dist/components/Avatar/Avatar.vue_vue_type_script_setup_true_lang.js +20 -14
  6. package/dist/components/Avatar/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/components/Board/Board.js.map +1 -1
  8. package/dist/components/Board/Board.vue.d.ts +6 -2
  9. package/dist/components/Board/Board.vue_vue_type_script_setup_true_lang.js +142 -74
  10. package/dist/components/Board/Board.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/components/Button/Button.js.map +1 -1
  12. package/dist/components/Button/Button.vue.d.ts +1 -1
  13. package/dist/components/Button/Button.vue_vue_type_script_setup_true_lang.js +4 -2
  14. package/dist/components/Button/Button.vue_vue_type_script_setup_true_lang.js.map +1 -1
  15. package/dist/components/ContextMenu/ContextMenu.js +7 -0
  16. package/dist/components/ContextMenu/ContextMenu.js.map +1 -0
  17. package/dist/components/ContextMenu/ContextMenu.vue.d.ts +44 -0
  18. package/dist/components/ContextMenu/ContextMenu.vue_vue_type_script_setup_true_lang.js +84 -0
  19. package/dist/components/ContextMenu/ContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  20. package/dist/components/ContextMenu/index.d.ts +2 -0
  21. package/dist/components/DataList/DataList.js.map +1 -1
  22. package/dist/components/DataList/DataList.vue.d.ts +8 -0
  23. package/dist/components/DataList/DataList.vue_vue_type_script_setup_true_lang.js +71 -52
  24. package/dist/components/DataList/DataList.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/DataList/types.d.ts +5 -1
  26. package/dist/components/Dialog/Dialog.js.map +1 -1
  27. package/dist/components/Dialog/Dialog.vue.d.ts +22 -6
  28. package/dist/components/Dialog/Dialog.vue_vue_type_script_setup_true_lang.js +174 -72
  29. package/dist/components/Dialog/Dialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/Dialog/useSheetDrag.d.ts +16 -0
  31. package/dist/components/Dialog/useSheetDrag.js +37 -0
  32. package/dist/components/Dialog/useSheetDrag.js.map +1 -0
  33. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  34. package/dist/components/DropdownMenu/DropdownMenu.vue.d.ts +6 -30
  35. package/dist/components/DropdownMenu/DropdownMenu.vue_vue_type_script_setup_true_lang.js +54 -74
  36. package/dist/components/DropdownMenu/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  38. package/dist/components/EmptyState/EmptyState.vue.d.ts +9 -3
  39. package/dist/components/EmptyState/EmptyState.vue_vue_type_script_setup_true_lang.js +35 -7
  40. package/dist/components/EmptyState/EmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/Filters/FilterChip.js.map +1 -1
  42. package/dist/components/Filters/FilterChip.vue.d.ts +4 -1
  43. package/dist/components/Filters/FilterChip.vue_vue_type_script_setup_true_lang.js +29 -24
  44. package/dist/components/Filters/FilterChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/Filters/FilterMenu.js.map +1 -1
  46. package/dist/components/Filters/FilterMenu.vue.d.ts +20 -1
  47. package/dist/components/Filters/FilterMenu.vue_vue_type_script_setup_true_lang.js +78 -56
  48. package/dist/components/Filters/FilterMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/Filters/SortMenu.js.map +1 -1
  50. package/dist/components/Filters/SortMenu.vue.d.ts +21 -1
  51. package/dist/components/Filters/SortMenu.vue_vue_type_script_setup_true_lang.js +90 -66
  52. package/dist/components/Filters/SortMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/Filters/index.d.ts +2 -1
  54. package/dist/components/Filters/trigger.d.ts +17 -0
  55. package/dist/components/Filters/trigger.js +33 -0
  56. package/dist/components/Filters/trigger.js.map +1 -0
  57. package/dist/components/Filters/types.d.ts +8 -0
  58. package/dist/components/FormField/FormField.js.map +1 -1
  59. package/dist/components/FormField/FormField.vue.d.ts +10 -0
  60. package/dist/components/FormField/FormField.vue_vue_type_script_setup_true_lang.js +31 -20
  61. package/dist/components/FormField/FormField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  62. package/dist/components/Icon/iconSet.js +9 -1
  63. package/dist/components/Icon/iconSet.js.map +1 -1
  64. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  65. package/dist/components/SegmentedControl/SegmentedControl.vue.d.ts +6 -3
  66. package/dist/components/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js +20 -17
  67. package/dist/components/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/SegmentedControl/index.d.ts +1 -1
  69. package/dist/components/Table/Table.js.map +1 -1
  70. package/dist/components/Table/Table.vue.d.ts +4 -0
  71. package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js +66 -56
  72. package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js.map +1 -1
  73. package/dist/components/Table/types.d.ts +2 -0
  74. package/dist/components/Tag/Tag.js.map +1 -1
  75. package/dist/components/Tag/Tag.vue.d.ts +16 -3
  76. package/dist/components/Tag/Tag.vue_vue_type_script_setup_true_lang.js +42 -19
  77. package/dist/components/Tag/Tag.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/Toast/ToastMessage.js.map +1 -1
  79. package/dist/components/Toast/ToastMessage.vue.d.ts +13 -1
  80. package/dist/components/Toast/ToastMessage.vue_vue_type_script_setup_true_lang.js +58 -23
  81. package/dist/components/Toast/ToastMessage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/Toast/Toaster.js.map +1 -1
  83. package/dist/components/Toast/Toaster.vue.d.ts +7 -3
  84. package/dist/components/Toast/Toaster.vue_vue_type_script_setup_true_lang.js +50 -21
  85. package/dist/components/Toast/Toaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/internal/MenuItemContent.js +7 -0
  87. package/dist/components/internal/MenuItemContent.js.map +1 -0
  88. package/dist/components/internal/MenuItemContent.vue.d.ts +7 -0
  89. package/dist/components/internal/MenuItemContent.vue_vue_type_script_setup_true_lang.js +26 -0
  90. package/dist/components/internal/MenuItemContent.vue_vue_type_script_setup_true_lang.js.map +1 -0
  91. package/dist/components/internal/menu.d.ts +46 -0
  92. package/dist/components/internal/menu.js +33 -0
  93. package/dist/components/internal/menu.js.map +1 -0
  94. package/dist/composables/toast.d.ts +20 -5
  95. package/dist/composables/toast.js +28 -20
  96. package/dist/composables/toast.js.map +1 -1
  97. package/dist/index.d.ts +2 -1
  98. package/dist/index.js +34 -33
  99. package/package.json +1 -1
  100. package/src/styles/tailwind.css +29 -0
@@ -1,9 +1,9 @@
1
1
  import e from "../Icon/Icon.js";
2
2
  import t from "../Checkbox/Checkbox.js";
3
- import n from "../Input/Input.js";
4
- import ee from "../SegmentedControl/SegmentedControl.js";
5
- import r from "../internal/CheckIcon.js";
6
- import te from "./FilterFrame.js";
3
+ import ee from "../Input/Input.js";
4
+ import te from "../SegmentedControl/SegmentedControl.js";
5
+ import n from "../internal/CheckIcon.js";
6
+ import r from "./FilterFrame.js";
7
7
  import i from "./FilterGlyph.js";
8
8
  import { datePresets as a, describeFilter as o, filterOperators as s } from "./defaults.js";
9
9
  import { Fragment as c, computed as l, createBlock as u, createCommentVNode as d, createElementBlock as f, createElementVNode as p, createTextVNode as m, createVNode as h, defineComponent as g, mergeModels as _, mergeProps as v, normalizeClass as y, openBlock as b, ref as ne, renderList as x, renderSlot as re, toDisplayString as S, unref as C, useAttrs as ie, useModel as w, vModelText as ae, withCtx as T, withDirectives as oe } from "vue";
@@ -34,6 +34,7 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
34
34
  icon: { default: void 0 },
35
35
  operators: { default: void 0 },
36
36
  options: { default: () => [] },
37
+ summary: { default: void 0 },
37
38
  status: { default: void 0 },
38
39
  valueLabel: { default: "values" },
39
40
  datePresets: { default: () => a },
@@ -76,25 +77,29 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
76
77
  "update:open"
77
78
  ],
78
79
  setup(a) {
79
- let g = a, _ = w(a, "op"), G = w(a, "modelValue"), K = w(a, "open"), q = ie(), J = l(() => g.operators ?? s[g.type]), Y = l(() => J.value.find((e) => e.value === _.value)), X = l(() => !Y.value?.noValue), Z = l(() => X.value ? o(G.value, g.options, {
80
+ let g = a, _ = w(a, "op"), G = w(a, "modelValue"), K = w(a, "open"), q = ie(), J = l(() => g.operators ?? s[g.type]), Y = l(() => J.value.find((e) => e.value === _.value)), X = l(() => !Y.value?.noValue), _e = l(() => X.value ? o(G.value, g.options, {
80
81
  valueLabel: g.valueLabel,
81
82
  yesLabel: g.yesLabel,
82
83
  noLabel: g.noLabel
83
- }) : ""), _e = l(() => [
84
+ }) : ""), Z = l(() => ({
85
+ field: g.summary?.field ?? g.field,
86
+ op: g.summary ? g.summary.op : Y.value?.label,
87
+ value: g.summary ? g.summary.value : _e.value
88
+ })), ve = l(() => [
84
89
  "enum",
85
90
  "person",
86
91
  "company"
87
- ].includes(g.type)), Q = ne(""), ve = l(() => {
92
+ ].includes(g.type)), Q = ne(""), ye = l(() => {
88
93
  let e = Q.value.trim().toLowerCase();
89
94
  return e ? g.options.filter((t) => t.label.toLowerCase().includes(e)) : g.options;
90
95
  }), $ = l(() => Array.isArray(G.value) ? G.value : []);
91
- function ye(e) {
96
+ function be(e) {
92
97
  G.value = $.value.includes(e) ? $.value.filter((t) => t !== e) : [...$.value, e];
93
98
  }
94
- function be() {
99
+ function xe() {
95
100
  K.value = !1, g.onRemove?.();
96
101
  }
97
- let xe = {
102
+ let Se = {
98
103
  blue: "bg-sui-hue-blue-ink",
99
104
  green: "bg-sui-hue-green-ink",
100
105
  orange: "bg-sui-hue-orange-ink",
@@ -125,9 +130,9 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
125
130
  name: a.type
126
131
  }, null, 8, ["name"])),
127
132
  p("span", null, [
128
- p("span", j, S(a.field), 1),
129
- Y.value ? (b(), f(c, { key: 0 }, [m(S(" ") + S(Y.value.label), 1)], 64)) : d("", !0),
130
- Z.value ? (b(), f(c, { key: 1 }, [s[7] ||= m(S(" "), -1), p("span", M, S(Z.value), 1)], 64)) : d("", !0)
133
+ p("span", j, S(Z.value.field), 1),
134
+ Z.value.op ? (b(), f(c, { key: 0 }, [m(S(" ") + S(Z.value.op), 1)], 64)) : d("", !0),
135
+ Z.value.value ? (b(), f(c, { key: 1 }, [s[7] ||= m(S(" "), -1), p("span", M, S(Z.value.value), 1)], 64)) : d("", !0)
131
136
  ]),
132
137
  s[8] ||= p("svg", {
133
138
  "aria-hidden": "true",
@@ -144,7 +149,7 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
144
149
  class: "z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in",
145
150
  "side-offset": 8
146
151
  }, {
147
- default: T(() => [h(te, {
152
+ default: T(() => [h(r, {
148
153
  "close-label": a.closeLabel,
149
154
  "enter-label": a.doneLabel,
150
155
  status: a.status,
@@ -189,7 +194,7 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
189
194
  class: "flex h-8 cursor-pointer items-center justify-between rounded-md px-2.5 text-13.5 text-sui-ink-body outline-hidden select-none data-highlighted:bg-sui-sunken data-[state=checked]:font-semibold data-[state=checked]:text-sui-ink",
190
195
  value: e.value
191
196
  }, {
192
- default: T(() => [m(S(e.label) + " ", 1), e.value === _.value ? (b(), u(r, { key: 0 })) : d("", !0)]),
197
+ default: T(() => [m(S(e.label) + " ", 1), e.value === _.value ? (b(), u(n, { key: 0 })) : d("", !0)]),
193
198
  _: 2
194
199
  }, 1032, ["value"]))), 128))]),
195
200
  _: 1
@@ -204,9 +209,9 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
204
209
  key: 4,
205
210
  class: "ml-auto inline-flex h-7 items-center gap-1.5 rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-danger-soft hover:text-sui-danger focus-visible:sui-ring-inset",
206
211
  type: "button",
207
- onClick: be
212
+ onClick: xe
208
213
  }, [h(i, { name: "trash" }), m(" " + S(a.removeLabel), 1)])) : d("", !0)
209
- ]), o.$slots.default ? re(o.$slots, "default", {}, void 0, void 0, 0) : X.value ? (b(), f(c, { key: 1 }, [_e.value ? (b(), f(c, { key: 0 }, [a.options.length > 6 ? (b(), f("div", I, [h(i, {
214
+ ]), o.$slots.default ? re(o.$slots, "default", {}, void 0, void 0, 0) : X.value ? (b(), f(c, { key: 1 }, [ve.value ? (b(), f(c, { key: 0 }, [a.options.length > 6 ? (b(), f("div", I, [h(i, {
210
215
  class: "size-4",
211
216
  name: "search"
212
217
  }), oe(p("input", {
@@ -215,21 +220,21 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
215
220
  autofocus: "",
216
221
  class: "h-full min-w-0 flex-1 border-none bg-transparent p-0 text-sm text-sui-ink shadow-none outline-hidden placeholder:text-sui-ink-faint focus:border-none focus:shadow-none focus:ring-0 focus:outline-hidden",
217
222
  placeholder: a.searchPlaceholder
218
- }, null, 8, L), [[ae, Q.value]])])) : d("", !0), p("div", R, [(b(!0), f(c, null, x(ve.value, (e) => (b(), f("label", {
223
+ }, null, 8, L), [[ae, Q.value]])])) : d("", !0), p("div", R, [(b(!0), f(c, null, x(ye.value, (e) => (b(), f("label", {
219
224
  key: e.value,
220
225
  class: y([H, $.value.includes(e.value) ? U : W])
221
226
  }, [
222
227
  h(t, {
223
228
  "model-value": $.value.includes(e.value),
224
- "onUpdate:modelValue": (t) => ye(e.value)
229
+ "onUpdate:modelValue": (t) => be(e.value)
225
230
  }, null, 8, ["model-value", "onUpdate:modelValue"]),
226
231
  e.color ? (b(), f("span", {
227
232
  key: 0,
228
- class: y(["size-1.5 shrink-0 rounded-full", xe[e.color]])
233
+ class: y(["size-1.5 shrink-0 rounded-full", Se[e.color]])
229
234
  }, null, 2)) : d("", !0),
230
235
  p("span", z, S(e.label), 1),
231
236
  e.count == null ? d("", !0) : (b(), f("span", B, S(e.count), 1))
232
- ], 2))), 128))])], 64)) : a.type === "text" || a.type === "number" ? (b(), f("div", me, [h(n, {
237
+ ], 2))), 128))])], 64)) : a.type === "text" || a.type === "number" ? (b(), f("div", me, [h(ee, {
233
238
  "aria-label": a.field,
234
239
  autofocus: "",
235
240
  "model-value": G.value == null ? "" : String(G.value),
@@ -259,14 +264,14 @@ var j = { class: "font-medium" }, M = { class: "font-semibold" }, N = { class: "
259
264
  name: "date"
260
265
  }, null, 8, ["class"]),
261
266
  p("span", he, S(e), 1),
262
- e === G.value ? (b(), u(r, { key: 0 })) : d("", !0)
267
+ e === G.value ? (b(), u(n, { key: 0 })) : d("", !0)
263
268
  ]),
264
269
  _: 2
265
270
  }, 1032, ["class", "value"]))), 128))]),
266
271
  _: 1
267
- }, 8, ["aria-label", "model-value"])) : a.type === "boolean" ? (b(), f("div", ge, [h(ee, {
272
+ }, 8, ["aria-label", "model-value"])) : a.type === "boolean" ? (b(), f("div", ge, [h(te, {
268
273
  "aria-label": a.field,
269
- "model-value": G.value ? "yes" : "no",
274
+ "model-value": G.value === null ? "" : G.value ? "yes" : "no",
270
275
  options: [{
271
276
  value: "yes",
272
277
  label: a.yesLabel
@@ -1 +1 @@
1
- {"version":3,"file":"FilterChip.vue_vue_type_script_setup_true_lang.js","names":["$slots","defaultDatePresets","_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_createVNode","FilterGlyph","_createTextVNode","_toDisplayString","_createBlock","_withCtx","Icon","_createElementVNode","_Fragment","_createCommentVNode","FilterFrame","_renderList","CheckIcon","_renderSlot","_withDirectives","_vModelText","_normalizeClass","Checkbox","Input","SegmentedControl","Icon_default","Checkbox_default","Input_default","SegmentedControl_default","CheckIcon_default","FilterFrame_default","FilterGlyph_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","chip","row","rowOn","rowOff","FilterChip_vue_vue_type_script_setup_true_lang_default","datePresets","\"op\"","\"opModifiers\"","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","op","useModel","value","open","attrs","useAttrs","ops","computed","filterOperators","current","o","needsValue","text","describeFilter","isChecklist","query","ref","listed","q","picked","toggle","choice","v","remove","hueDots","openBlock","createElementBlock","mergeProps","unref","createVNode","createTextVNode","toDisplayString","createBlock","PopoverRoot","_cache","$event","withCtx","PopoverTrigger","createElementVNode","Fragment","createCommentVNode","PopoverPortal","PopoverContent","DropdownMenuRoot","DropdownMenuTrigger","DropdownMenuPortal","DropdownMenuContent","DropdownMenuRadioGroup","renderList","DropdownMenuRadioItem","operator","_ctx","renderSlot","withDirectives","vModelText","option","normalizeClass","RadioGroupRoot","RadioGroupItem","preset"],"sources":["../../../src/components/Filters/FilterChip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\n\nimport {\n DropdownMenuContent,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuRoot,\n DropdownMenuTrigger,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n RadioGroupItem,\n RadioGroupRoot\n} from 'reka-ui'\n\nimport Checkbox from '../Checkbox/Checkbox.vue'\nimport Icon from '../Icon/Icon.vue'\nimport Input from '../Input/Input.vue'\nimport SegmentedControl from '../SegmentedControl/SegmentedControl.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport { datePresets as defaultDatePresets, describeFilter, filterOperators } from './defaults'\nimport type { FilterFieldType, FilterOperator, FilterOption, FilterValue } from './types'\n\nexport interface FilterChipProps {\n /** A filter, read as a sentence; `add` is the quiet \"+ Filter\" that starts one (FilterMenu includes it). */\n kind?: 'filter' | 'add'\n field?: string\n /** Picks the editor: a checklist for enum, person and company, an input for text and number, presets for date, Yes / No for boolean. */\n type?: FilterFieldType\n /** An app icon for the field, instead of the type's glyph. */\n icon?: string\n /** The operators offered; English ones by type by default. */\n operators?: FilterOperator[]\n /** The choices for enum, person and company. */\n options?: FilterOption[]\n /** The live result count in the panel's footer, e.g. \"120 people\". */\n status?: string\n /** The plural noun once more than two values are picked: \"3 stages\". */\n valueLabel?: string\n datePresets?: string[]\n /** Adds a Remove action to the panel (`@remove`). */\n onRemove?: () => void\n removeLabel?: string\n addLabel?: string\n operatorLabel?: string\n searchPlaceholder?: string\n valuePlaceholder?: string\n doneLabel?: string\n closeLabel?: string\n yesLabel?: string\n noLabel?: string\n}\n\n// Attributes and listeners go to the chip itself; the root is a renderless popover.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FilterChipProps>(), {\n kind: 'filter',\n field: undefined,\n type: 'enum',\n icon: undefined,\n operators: undefined,\n options: () => [],\n status: undefined,\n valueLabel: 'values',\n datePresets: () => defaultDatePresets,\n onRemove: undefined,\n removeLabel: 'Remove',\n addLabel: 'Filter',\n operatorLabel: 'Operator',\n searchPlaceholder: 'Search…',\n valuePlaceholder: 'Type a value',\n doneLabel: 'Done',\n closeLabel: 'Close',\n yesLabel: 'Yes',\n noLabel: 'No'\n})\n\nconst op = defineModel<string>('op')\nconst value = defineModel<FilterValue>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n /** Your own editor, in place of the type's. */\n default?: () => unknown\n}>()\n\nconst attrs = useAttrs()\n\nconst ops = computed(() => props.operators ?? filterOperators[props.type])\nconst current = computed(() => ops.value.find((o) => o.value === op.value))\nconst needsValue = computed(() => !current.value?.noValue)\nconst text = computed(() =>\n needsValue.value\n ? describeFilter(value.value, props.options, {\n valueLabel: props.valueLabel,\n yesLabel: props.yesLabel,\n noLabel: props.noLabel\n })\n : ''\n)\nconst isChecklist = computed(() => ['enum', 'person', 'company'].includes(props.type))\n\nconst query = ref('')\nconst listed = computed(() => {\n const q = query.value.trim().toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nconst picked = computed(() => (Array.isArray(value.value) ? value.value : []))\n\nfunction toggle(choice: string | number) {\n value.value = picked.value.includes(choice) ? picked.value.filter((v) => v !== choice) : [...picked.value, choice]\n}\n\nfunction remove() {\n open.value = false\n props.onRemove?.()\n}\n\nconst chip =\n 'inline-flex h-7.5 items-center gap-1.5 rounded-lg border text-13 whitespace-nowrap outline-hidden transition-[border-color,box-shadow] duration-150 focus-visible:sui-ring'\nconst row =\n 'flex min-h-8 w-full cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-left text-13.5 outline-hidden transition-colors duration-100 focus-visible:sui-ring-inset'\nconst rowOn = 'bg-sui-accent-wash font-semibold text-sui-accent'\nconst rowOff = 'text-sui-ink hover:bg-sui-sunken'\nconst hueDots: Record<string, string> = {\n blue: 'bg-sui-hue-blue-ink',\n green: 'bg-sui-hue-green-ink',\n orange: 'bg-sui-hue-orange-ink',\n pink: 'bg-sui-hue-pink-ink',\n purple: 'bg-sui-hue-purple-ink',\n slate: 'bg-sui-hue-slate-ink',\n red: 'bg-sui-hue-red-ink',\n amber: 'bg-sui-hue-amber-ink'\n}\n</script>\n\n<!-- A view's filter as a sentence chip (\"Stage is any of Lead, Customer\"), whose panel changes it as you go. -->\n<template>\n <button\n v-if=\"kind === 'add'\"\n v-bind=\"attrs\"\n class=\"border-dashed border-sui-line-strong px-2 font-medium text-sui-ink-muted hover:border-sui-ink-muted hover:text-sui-ink-body\"\n :class=\"chip\"\n type=\"button\"\n >\n <FilterGlyph name=\"plus\" />\n {{ addLabel }}\n </button>\n <PopoverRoot v-else v-model:open=\"open\">\n <PopoverTrigger\n v-bind=\"attrs\"\n class=\"border-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-sui-accent hover:border-sui-accent-bright data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n :class=\"chip\"\n >\n <Icon v-if=\"icon\" class=\"size-3.5 opacity-80\" color=\"accent\" :name=\"icon\" />\n <FilterGlyph v-else class=\"opacity-80\" :name=\"type\" />\n <!-- Real spaces between the words, so the chip's name reads as a sentence. -->\n <span\n ><span class=\"font-medium\">{{ field }}</span\n ><template v-if=\"current\">{{ ' ' }}{{ current.label }}</template\n ><template v-if=\"text\"\n >{{ ' ' }}<span class=\"font-semibold\">{{ text }}</span></template\n ></span\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 shrink-0 fill-none stroke-current opacity-70\"\n stroke-linecap=\"round\"\n stroke-width=\"2.2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n </PopoverTrigger>\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n class=\"z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in\"\n :side-offset=\"8\"\n >\n <FilterFrame :close-label=\"closeLabel\" :enter-label=\"doneLabel\" :status=\"status\" @enter=\"open = false\">\n <div class=\"flex h-11 items-center gap-1.5 pr-1.5 pl-3.5 text-sui-ink-muted\">\n <Icon v-if=\"icon\" color=\"ink-muted\" :name=\"icon\" />\n <FilterGlyph v-else class=\"size-4\" :name=\"type\" />\n <span class=\"text-sm font-semibold text-sui-ink\">{{ field }}</span>\n <DropdownMenuRoot v-if=\"ops.length > 1\">\n <DropdownMenuTrigger\n :aria-label=\"`${operatorLabel}: ${current?.label ?? ''}`\"\n class=\"inline-flex h-7 items-center gap-0.5 rounded-md pr-1 pl-1.5 text-13.5 font-medium text-sui-accent outline-hidden transition-colors duration-150 hover:bg-sui-accent-wash focus-visible:sui-ring-inset data-[state=open]:bg-sui-accent-wash\"\n >\n {{ current?.label }}\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-width=\"2.2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n </DropdownMenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuContent\n align=\"start\"\n class=\"z-[1100] w-44 rounded-lg border border-sui-line bg-sui-surface p-1 shadow-lg data-[state=open]:animate-sui-menu-in\"\n :side-offset=\"4\"\n >\n <DropdownMenuRadioGroup v-model=\"op\">\n <DropdownMenuRadioItem\n v-for=\"operator in ops\"\n :key=\"operator.value\"\n class=\"flex h-8 cursor-pointer items-center justify-between rounded-md px-2.5 text-13.5 text-sui-ink-body outline-hidden select-none data-highlighted:bg-sui-sunken data-[state=checked]:font-semibold data-[state=checked]:text-sui-ink\"\n :value=\"operator.value\"\n >\n {{ operator.label }}\n <CheckIcon v-if=\"operator.value === op\" />\n </DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenuRoot>\n <span v-else class=\"text-13.5 text-sui-ink-muted\">{{ current?.label }}</span>\n <button\n v-if=\"onRemove\"\n class=\"ml-auto inline-flex h-7 items-center gap-1.5 rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-danger-soft hover:text-sui-danger focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"remove\"\n >\n <FilterGlyph name=\"trash\" />\n {{ removeLabel }}\n </button>\n </div>\n\n <slot v-if=\"$slots.default\" />\n <template v-else-if=\"needsValue\">\n <template v-if=\"isChecklist\">\n <div\n v-if=\"options.length > 6\"\n class=\"mx-2 mb-1 flex h-9 items-center gap-2 rounded-lg border border-sui-line-subtle px-2.5 text-sui-ink-muted\"\n >\n <FilterGlyph class=\"size-4\" name=\"search\" />\n <!-- focus: classes too: an app's forms plugin rings focused text fields, and outranks plain utilities. -->\n <input\n v-model=\"query\"\n :aria-label=\"searchPlaceholder\"\n autofocus\n class=\"h-full min-w-0 flex-1 border-none bg-transparent p-0 text-sm text-sui-ink shadow-none outline-hidden placeholder:text-sui-ink-faint focus:border-none focus:shadow-none focus:ring-0 focus:outline-hidden\"\n :placeholder=\"searchPlaceholder\"\n />\n </div>\n <div class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\">\n <label\n v-for=\"option in listed\"\n :key=\"option.value\"\n :class=\"[row, picked.includes(option.value) ? rowOn : rowOff]\"\n >\n <Checkbox :model-value=\"picked.includes(option.value)\" @update:model-value=\"toggle(option.value)\" />\n <span v-if=\"option.color\" class=\"size-1.5 shrink-0 rounded-full\" :class=\"hueDots[option.color]\" />\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <span v-if=\"option.count != null\" class=\"text-xs font-normal text-sui-ink-muted tabular-nums\">{{\n option.count\n }}</span>\n </label>\n </div>\n </template>\n <div v-else-if=\"type === 'text' || type === 'number'\" class=\"px-2 pt-1 pb-2\">\n <Input\n :aria-label=\"field\"\n autofocus\n :model-value=\"value == null ? '' : String(value)\"\n :placeholder=\"valuePlaceholder\"\n :type=\"type === 'number' ? 'number' : 'text'\"\n @update:model-value=\"value = $event ?? null\"\n />\n </div>\n <RadioGroupRoot\n v-else-if=\"type === 'date'\"\n :aria-label=\"field\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"typeof value === 'string' ? value : undefined\"\n @update:model-value=\"value = String($event)\"\n >\n <RadioGroupItem\n v-for=\"preset in datePresets\"\n :key=\"preset\"\n :class=\"[row, preset === value ? rowOn : rowOff]\"\n :value=\"preset\"\n >\n <FilterGlyph\n class=\"size-4\"\n :class=\"preset === value ? 'text-sui-accent' : 'text-sui-ink-muted'\"\n name=\"date\"\n />\n <span class=\"min-w-0 flex-1 truncate\">{{ preset }}</span>\n <CheckIcon v-if=\"preset === value\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <div v-else-if=\"type === 'boolean'\" class=\"px-2.5 pt-1 pb-2.5\">\n <SegmentedControl\n :aria-label=\"field\"\n :model-value=\"value ? 'yes' : 'no'\"\n :options=\"[\n { value: 'yes', label: yesLabel },\n { value: 'no', label: noLabel }\n ]\"\n @update:model-value=\"value = $event === 'yes'\"\n />\n </div>\n </template>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"FilterChip.vue_vue_type_script_setup_true_lang.js","names":["$slots","defaultDatePresets","_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_createVNode","FilterGlyph","_createTextVNode","_toDisplayString","_createBlock","_withCtx","Icon","_createElementVNode","_Fragment","_createCommentVNode","FilterFrame","_renderList","CheckIcon","_renderSlot","_withDirectives","_vModelText","_normalizeClass","Checkbox","Input","SegmentedControl","Icon_default","Checkbox_default","Input_default","SegmentedControl_default","CheckIcon_default","FilterFrame_default","FilterGlyph_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","chip","row","rowOn","rowOff","FilterChip_vue_vue_type_script_setup_true_lang_default","datePresets","\"op\"","\"opModifiers\"","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","op","useModel","value","open","attrs","useAttrs","ops","computed","filterOperators","current","o","needsValue","text","describeFilter","words","isChecklist","query","ref","listed","q","picked","toggle","choice","v","remove","hueDots","openBlock","createElementBlock","mergeProps","unref","createVNode","createTextVNode","toDisplayString","createBlock","PopoverRoot","_cache","$event","withCtx","PopoverTrigger","createElementVNode","Fragment","createCommentVNode","PopoverPortal","PopoverContent","DropdownMenuRoot","DropdownMenuTrigger","DropdownMenuPortal","DropdownMenuContent","DropdownMenuRadioGroup","renderList","DropdownMenuRadioItem","operator","_ctx","renderSlot","withDirectives","vModelText","option","normalizeClass","RadioGroupRoot","RadioGroupItem","preset"],"sources":["../../../src/components/Filters/FilterChip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\n\nimport {\n DropdownMenuContent,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuRoot,\n DropdownMenuTrigger,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n RadioGroupItem,\n RadioGroupRoot\n} from 'reka-ui'\n\nimport Checkbox from '../Checkbox/Checkbox.vue'\nimport Icon from '../Icon/Icon.vue'\nimport Input from '../Input/Input.vue'\nimport SegmentedControl from '../SegmentedControl/SegmentedControl.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport { datePresets as defaultDatePresets, describeFilter, filterOperators } from './defaults'\nimport type { FilterFieldType, FilterOperator, FilterOption, FilterSummary, FilterValue } from './types'\n\nexport interface FilterChipProps {\n /** A filter, read as a sentence; `add` is the quiet \"+ Filter\" that starts one (FilterMenu includes it). */\n kind?: 'filter' | 'add'\n field?: string\n /** Picks the editor: a checklist for enum, person and company, an input for text and number, presets for date, Yes / No for boolean. */\n type?: FilterFieldType\n /** An app icon for the field, instead of the type's glyph. */\n icon?: string\n /** The operators offered; English ones by type by default. */\n operators?: FilterOperator[]\n /** The choices for enum, person and company. */\n options?: FilterOption[]\n /** Your own wording for the chip, in place of field, operator and value: \"Not archived\", \"Created in the last 7 days\". */\n summary?: FilterSummary\n /** The live result count in the panel's footer, e.g. \"120 people\". */\n status?: string\n /** The plural noun once more than two values are picked: \"3 stages\". */\n valueLabel?: string\n datePresets?: string[]\n /** Adds a Remove action to the panel (`@remove`). */\n onRemove?: () => void\n removeLabel?: string\n addLabel?: string\n operatorLabel?: string\n searchPlaceholder?: string\n valuePlaceholder?: string\n doneLabel?: string\n closeLabel?: string\n yesLabel?: string\n noLabel?: string\n}\n\n// Attributes and listeners go to the chip itself; the root is a renderless popover.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FilterChipProps>(), {\n kind: 'filter',\n field: undefined,\n type: 'enum',\n icon: undefined,\n operators: undefined,\n options: () => [],\n summary: undefined,\n status: undefined,\n valueLabel: 'values',\n datePresets: () => defaultDatePresets,\n onRemove: undefined,\n removeLabel: 'Remove',\n addLabel: 'Filter',\n operatorLabel: 'Operator',\n searchPlaceholder: 'Search…',\n valuePlaceholder: 'Type a value',\n doneLabel: 'Done',\n closeLabel: 'Close',\n yesLabel: 'Yes',\n noLabel: 'No'\n})\n\nconst op = defineModel<string>('op')\nconst value = defineModel<FilterValue>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n /** Your own editor, in place of the type's. */\n default?: () => unknown\n}>()\n\nconst attrs = useAttrs()\n\nconst ops = computed(() => props.operators ?? filterOperators[props.type])\nconst current = computed(() => ops.value.find((o) => o.value === op.value))\nconst needsValue = computed(() => !current.value?.noValue)\nconst text = computed(() =>\n needsValue.value\n ? describeFilter(value.value, props.options, {\n valueLabel: props.valueLabel,\n yesLabel: props.yesLabel,\n noLabel: props.noLabel\n })\n : ''\n)\nconst words = computed(() => ({\n field: props.summary?.field ?? props.field,\n op: props.summary ? props.summary.op : current.value?.label,\n value: props.summary ? props.summary.value : text.value\n}))\nconst isChecklist = computed(() => ['enum', 'person', 'company'].includes(props.type))\n\nconst query = ref('')\nconst listed = computed(() => {\n const q = query.value.trim().toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nconst picked = computed(() => (Array.isArray(value.value) ? value.value : []))\n\nfunction toggle(choice: string | number) {\n value.value = picked.value.includes(choice) ? picked.value.filter((v) => v !== choice) : [...picked.value, choice]\n}\n\nfunction remove() {\n open.value = false\n props.onRemove?.()\n}\n\nconst chip =\n 'inline-flex h-7.5 items-center gap-1.5 rounded-lg border text-13 whitespace-nowrap outline-hidden transition-[border-color,box-shadow] duration-150 focus-visible:sui-ring'\nconst row =\n 'flex min-h-8 w-full cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-left text-13.5 outline-hidden transition-colors duration-100 focus-visible:sui-ring-inset'\nconst rowOn = 'bg-sui-accent-wash font-semibold text-sui-accent'\nconst rowOff = 'text-sui-ink hover:bg-sui-sunken'\nconst hueDots: Record<string, string> = {\n blue: 'bg-sui-hue-blue-ink',\n green: 'bg-sui-hue-green-ink',\n orange: 'bg-sui-hue-orange-ink',\n pink: 'bg-sui-hue-pink-ink',\n purple: 'bg-sui-hue-purple-ink',\n slate: 'bg-sui-hue-slate-ink',\n red: 'bg-sui-hue-red-ink',\n amber: 'bg-sui-hue-amber-ink'\n}\n</script>\n\n<!-- A view's filter as a sentence chip (\"Stage is any of Lead, Customer\"), whose panel changes it as you go. -->\n<template>\n <button\n v-if=\"kind === 'add'\"\n v-bind=\"attrs\"\n class=\"border-dashed border-sui-line-strong px-2 font-medium text-sui-ink-muted hover:border-sui-ink-muted hover:text-sui-ink-body\"\n :class=\"chip\"\n type=\"button\"\n >\n <FilterGlyph name=\"plus\" />\n {{ addLabel }}\n </button>\n <PopoverRoot v-else v-model:open=\"open\">\n <PopoverTrigger\n v-bind=\"attrs\"\n class=\"border-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-sui-accent hover:border-sui-accent-bright data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n :class=\"chip\"\n >\n <Icon v-if=\"icon\" class=\"size-3.5 opacity-80\" color=\"accent\" :name=\"icon\" />\n <FilterGlyph v-else class=\"opacity-80\" :name=\"type\" />\n <!-- Real spaces between the words, so the chip's name reads as a sentence. -->\n <span\n ><span class=\"font-medium\">{{ words.field }}</span\n ><template v-if=\"words.op\">{{ ' ' }}{{ words.op }}</template\n ><template v-if=\"words.value\"\n >{{ ' ' }}<span class=\"font-semibold\">{{ words.value }}</span></template\n ></span\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 shrink-0 fill-none stroke-current opacity-70\"\n stroke-linecap=\"round\"\n stroke-width=\"2.2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n </PopoverTrigger>\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n class=\"z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in\"\n :side-offset=\"8\"\n >\n <FilterFrame :close-label=\"closeLabel\" :enter-label=\"doneLabel\" :status=\"status\" @enter=\"open = false\">\n <div class=\"flex h-11 items-center gap-1.5 pr-1.5 pl-3.5 text-sui-ink-muted\">\n <Icon v-if=\"icon\" color=\"ink-muted\" :name=\"icon\" />\n <FilterGlyph v-else class=\"size-4\" :name=\"type\" />\n <span class=\"text-sm font-semibold text-sui-ink\">{{ field }}</span>\n <DropdownMenuRoot v-if=\"ops.length > 1\">\n <DropdownMenuTrigger\n :aria-label=\"`${operatorLabel}: ${current?.label ?? ''}`\"\n class=\"inline-flex h-7 items-center gap-0.5 rounded-md pr-1 pl-1.5 text-13.5 font-medium text-sui-accent outline-hidden transition-colors duration-150 hover:bg-sui-accent-wash focus-visible:sui-ring-inset data-[state=open]:bg-sui-accent-wash\"\n >\n {{ current?.label }}\n <svg\n aria-hidden=\"true\"\n class=\"size-3.5 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-width=\"2.2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M6 9l6 6 6-6\" />\n </svg>\n </DropdownMenuTrigger>\n <DropdownMenuPortal>\n <DropdownMenuContent\n align=\"start\"\n class=\"z-[1100] w-44 rounded-lg border border-sui-line bg-sui-surface p-1 shadow-lg data-[state=open]:animate-sui-menu-in\"\n :side-offset=\"4\"\n >\n <DropdownMenuRadioGroup v-model=\"op\">\n <DropdownMenuRadioItem\n v-for=\"operator in ops\"\n :key=\"operator.value\"\n class=\"flex h-8 cursor-pointer items-center justify-between rounded-md px-2.5 text-13.5 text-sui-ink-body outline-hidden select-none data-highlighted:bg-sui-sunken data-[state=checked]:font-semibold data-[state=checked]:text-sui-ink\"\n :value=\"operator.value\"\n >\n {{ operator.label }}\n <CheckIcon v-if=\"operator.value === op\" />\n </DropdownMenuRadioItem>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenuRoot>\n <span v-else class=\"text-13.5 text-sui-ink-muted\">{{ current?.label }}</span>\n <button\n v-if=\"onRemove\"\n class=\"ml-auto inline-flex h-7 items-center gap-1.5 rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-danger-soft hover:text-sui-danger focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"remove\"\n >\n <FilterGlyph name=\"trash\" />\n {{ removeLabel }}\n </button>\n </div>\n\n <slot v-if=\"$slots.default\" />\n <template v-else-if=\"needsValue\">\n <template v-if=\"isChecklist\">\n <div\n v-if=\"options.length > 6\"\n class=\"mx-2 mb-1 flex h-9 items-center gap-2 rounded-lg border border-sui-line-subtle px-2.5 text-sui-ink-muted\"\n >\n <FilterGlyph class=\"size-4\" name=\"search\" />\n <!-- focus: classes too: an app's forms plugin rings focused text fields, and outranks plain utilities. -->\n <input\n v-model=\"query\"\n :aria-label=\"searchPlaceholder\"\n autofocus\n class=\"h-full min-w-0 flex-1 border-none bg-transparent p-0 text-sm text-sui-ink shadow-none outline-hidden placeholder:text-sui-ink-faint focus:border-none focus:shadow-none focus:ring-0 focus:outline-hidden\"\n :placeholder=\"searchPlaceholder\"\n />\n </div>\n <div class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\">\n <label\n v-for=\"option in listed\"\n :key=\"option.value\"\n :class=\"[row, picked.includes(option.value) ? rowOn : rowOff]\"\n >\n <Checkbox :model-value=\"picked.includes(option.value)\" @update:model-value=\"toggle(option.value)\" />\n <span v-if=\"option.color\" class=\"size-1.5 shrink-0 rounded-full\" :class=\"hueDots[option.color]\" />\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <span v-if=\"option.count != null\" class=\"text-xs font-normal text-sui-ink-muted tabular-nums\">{{\n option.count\n }}</span>\n </label>\n </div>\n </template>\n <div v-else-if=\"type === 'text' || type === 'number'\" class=\"px-2 pt-1 pb-2\">\n <Input\n :aria-label=\"field\"\n autofocus\n :model-value=\"value == null ? '' : String(value)\"\n :placeholder=\"valuePlaceholder\"\n :type=\"type === 'number' ? 'number' : 'text'\"\n @update:model-value=\"value = $event ?? null\"\n />\n </div>\n <RadioGroupRoot\n v-else-if=\"type === 'date'\"\n :aria-label=\"field\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"typeof value === 'string' ? value : undefined\"\n @update:model-value=\"value = String($event)\"\n >\n <RadioGroupItem\n v-for=\"preset in datePresets\"\n :key=\"preset\"\n :class=\"[row, preset === value ? rowOn : rowOff]\"\n :value=\"preset\"\n >\n <FilterGlyph\n class=\"size-4\"\n :class=\"preset === value ? 'text-sui-accent' : 'text-sui-ink-muted'\"\n name=\"date\"\n />\n <span class=\"min-w-0 flex-1 truncate\">{{ preset }}</span>\n <CheckIcon v-if=\"preset === value\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <div v-else-if=\"type === 'boolean'\" class=\"px-2.5 pt-1 pb-2.5\">\n <SegmentedControl\n :aria-label=\"field\"\n :model-value=\"value === null ? '' : value ? 'yes' : 'no'\"\n :options=\"[\n { value: 'yes', label: yesLabel },\n { value: 'no', label: noLabel }\n ]\"\n @update:model-value=\"value = $event === 'yes'\"\n />\n </div>\n </template>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterMenu.js","names":["_sfc_main","FilterMenu_vue_vue_type_script_setup_true_lang_default","FilterMenu_default"],"sources":["../../../src/components/Filters/FilterMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\n\nimport {\n ListboxContent,\n ListboxFilter,\n ListboxGroup,\n ListboxGroupLabel,\n ListboxItem,\n ListboxRoot,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger\n} from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport type { FilterField } from './types'\n\nexport interface FilterMenuProps {\n fields: FilterField[]\n /** Fields already filtering, marked \"In use\"; picking one should open its chip, not add a second. */\n inUse?: string[]\n /** chip: the dashed \"+ Filter\" in the view bar. button: the page header's Filters button, tinted while filters are in use. */\n as?: 'chip' | 'button'\n /** The footer's status; \"{count} fields\" by default. */\n status?: string\n label?: string\n buttonLabel?: string\n searchPlaceholder?: string\n inUseLabel?: string\n addLabel?: string\n closeLabel?: string\n /** `{count}` is the number of fields. */\n fieldsLabel?: string\n /** `{query}` is what was typed. */\n noMatchLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FilterMenuProps>(), {\n inUse: () => [],\n as: 'chip',\n status: undefined,\n label: 'Filter',\n buttonLabel: 'Filters',\n searchPlaceholder: 'Filter by…',\n inUseLabel: 'In use',\n addLabel: 'Add',\n closeLabel: 'Close',\n fieldsLabel: '{count} fields',\n noMatchLabel: 'No field matches “{query}”.'\n})\n\nconst emit = defineEmits<{ pick: [name: string] }>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\nconst attrs = useAttrs()\nconst query = ref('')\n// Only the keyboard's highlight gets the focus ring; the pointer's is just a tint.\nconst keyboard = ref(false)\n\nconst groups = computed(() => {\n const q = query.value.trim().toLowerCase()\n const shown = props.fields.filter((f) => !q || f.label.toLowerCase().includes(q))\n return [...new Set(shown.map((f) => f.group ?? ''))].map((name) => ({\n name,\n fields: shown.filter((f) => (f.group ?? '') === name)\n }))\n})\n\nfunction pick(name: unknown) {\n if (typeof name !== 'string') return\n open.value = false\n query.value = ''\n emit('pick', name)\n}\n\nfunction onOpen(isOpen: boolean) {\n if (!isOpen) query.value = ''\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) keyboard.value = true\n}\n</script>\n\n<!-- The field list behind \"+ Filter\": search, fields grouped with their type, and which are already filtering. -->\n<template>\n <PopoverRoot v-model:open=\"open\" @update:open=\"onOpen\">\n <PopoverTrigger v-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :variant=\"inUse.length ? 'tinted' : 'secondary'\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M2.5 3.5h11l-4.25 5v4l-2.5 1v-5z\" />\n </svg>\n {{ buttonLabel }}\n </Button>\n </PopoverTrigger>\n <PopoverTrigger\n v-else\n v-bind=\"attrs\"\n class=\"inline-flex h-7.5 items-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong px-2 text-13 font-medium whitespace-nowrap text-sui-ink-muted outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-ink-muted hover:text-sui-ink-body focus-visible:sui-ring data-[state=open]:border-solid data-[state=open]:border-sui-accent-solid data-[state=open]:text-sui-accent data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <FilterGlyph name=\"plus\" />\n {{ label }}\n </PopoverTrigger>\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n class=\"z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in\"\n :side-offset=\"8\"\n @keydown=\"onKeydown\"\n @pointermove=\"keyboard = false\"\n >\n <ListboxRoot highlight-on-hover @update:model-value=\"pick\">\n <FilterFrame\n :close-label=\"closeLabel\"\n :enter-label=\"addLabel\"\n :status=\"status ?? fieldsLabel.replace('{count}', String(fields.length))\"\n >\n <div class=\"flex h-11 items-center gap-2 border-b border-sui-line-subtle px-3.5 text-sui-ink-muted\">\n <FilterGlyph class=\"size-4\" name=\"search\" />\n <ListboxFilter\n v-model=\"query\"\n :aria-label=\"searchPlaceholder\"\n auto-focus\n class=\"h-full min-w-0 flex-1 border-none bg-transparent p-0 text-sm text-sui-ink shadow-none outline-hidden placeholder:text-sui-ink-faint focus:border-none focus:shadow-none focus:ring-0 focus:outline-hidden\"\n :placeholder=\"searchPlaceholder\"\n />\n </div>\n <ListboxContent\n :aria-label=\"searchPlaceholder\"\n class=\"group/list max-h-64 overflow-auto px-1.5 pt-1 pb-1.5 outline-hidden\"\n :data-keyboard=\"keyboard || undefined\"\n >\n <ListboxGroup v-for=\"group in groups\" :key=\"group.name\">\n <ListboxGroupLabel\n v-if=\"group.name\"\n class=\"m-0 px-2 pt-2.5 pb-1 text-11 font-semibold tracking-caps text-sui-ink-muted uppercase\"\n >\n {{ group.name }}\n </ListboxGroupLabel>\n <ListboxItem\n v-for=\"field in group.fields\"\n :key=\"field.name\"\n class=\"flex min-h-8 cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-13.5 text-sui-ink outline-hidden select-none data-highlighted:bg-sui-sunken group-data-keyboard/list:data-highlighted:sui-ring-inset\"\n :value=\"field.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md bg-sui-sunken text-sui-ink-body\"\n >\n <FilterGlyph :name=\"field.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ field.label }}</span>\n <span\n v-if=\"inUse.includes(field.name)\"\n class=\"inline-flex items-center gap-1.5 text-xs font-medium text-sui-accent\"\n >\n <span class=\"size-1.5 rounded-full bg-sui-accent-solid\" />\n {{ inUseLabel }}\n </span>\n </ListboxItem>\n </ListboxGroup>\n <p v-if=\"!groups.length\" class=\"m-0 px-2 py-3 text-13 text-sui-ink-body\">\n {{ noMatchLabel.replace('{query}', query) }}\n </p>\n </ListboxContent>\n </FilterFrame>\n </ListboxRoot>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"FilterMenu.js","names":["_sfc_main","FilterMenu_vue_vue_type_script_setup_true_lang_default","FilterMenu_default"],"sources":["../../../src/components/Filters/FilterMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\n\nimport {\n ListboxContent,\n ListboxFilter,\n ListboxGroup,\n ListboxGroupLabel,\n ListboxItem,\n ListboxRoot,\n PopoverAnchor,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger\n} from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport { type FilterTriggerProps, useCustomTrigger } from './trigger'\nimport type { FilterField } from './types'\n\nexport interface FilterMenuProps {\n fields: FilterField[]\n /** Fields already filtering, marked \"In use\"; picking one should open its chip, not add a second. */\n inUse?: string[]\n /** chip: the dashed \"+ Filter\" in the view bar. button: the page header's Filters button, tinted while filters are in use. */\n as?: 'chip' | 'button'\n /** as=\"button\" only: ghost for a page header. Secondary by default, tinted while filters are in use. */\n variant?: 'secondary' | 'ghost' | 'tinted'\n /** The footer's status; \"{count} fields\" by default. */\n status?: string\n label?: string\n buttonLabel?: string\n searchPlaceholder?: string\n inUseLabel?: string\n addLabel?: string\n closeLabel?: string\n /** `{count}` is the number of fields. */\n fieldsLabel?: string\n /** `{query}` is what was typed. */\n noMatchLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FilterMenuProps>(), {\n inUse: () => [],\n as: 'chip',\n variant: undefined,\n status: undefined,\n label: 'Filter',\n buttonLabel: 'Filters',\n searchPlaceholder: 'Filter by…',\n inUseLabel: 'In use',\n addLabel: 'Add',\n closeLabel: 'Close',\n fieldsLabel: '{count} fields',\n noMatchLabel: 'No field matches “{query}”.'\n})\n\nconst emit = defineEmits<{ pick: [name: string] }>()\n\nconst open = defineModel<boolean>('open', { default: false })\n\ndefineSlots<{\n /** Your own opener in place of the chip or button: spread `props` on it. `count` is the filters in use. */\n trigger?: (props: { open: boolean; toggle: () => void; count: number; props: FilterTriggerProps }) => unknown\n}>()\n\nconst attrs = useAttrs()\nconst custom = useCustomTrigger(open)\nconst query = ref('')\n// Only the keyboard's highlight gets the focus ring; the pointer's is just a tint.\nconst keyboard = ref(false)\n\nconst groups = computed(() => {\n const q = query.value.trim().toLowerCase()\n const shown = props.fields.filter((f) => !q || f.label.toLowerCase().includes(q))\n return [...new Set(shown.map((f) => f.group ?? ''))].map((name) => ({\n name,\n fields: shown.filter((f) => (f.group ?? '') === name)\n }))\n})\n\nfunction pick(name: unknown) {\n if (typeof name !== 'string') return\n open.value = false\n query.value = ''\n emit('pick', name)\n}\n\nfunction onOpen(isOpen: boolean) {\n if (!isOpen) query.value = ''\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) keyboard.value = true\n}\n</script>\n\n<!-- The field list behind \"+ Filter\": search, fields grouped with their type, and which are already filtering. -->\n<template>\n <PopoverRoot v-model:open=\"open\" @update:open=\"onOpen\">\n <PopoverAnchor v-if=\"$slots.trigger\" as-child>\n <slot :count=\"inUse.length\" name=\"trigger\" :open=\"open\" :props=\"custom.props.value\" :toggle=\"custom.toggle\" />\n </PopoverAnchor>\n <PopoverTrigger v-else-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :variant=\"variant ?? (inUse.length ? 'tinted' : 'secondary')\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M2.5 3.5h11l-4.25 5v4l-2.5 1v-5z\" />\n </svg>\n {{ buttonLabel }}\n </Button>\n </PopoverTrigger>\n <PopoverTrigger\n v-else\n v-bind=\"attrs\"\n class=\"inline-flex h-7.5 items-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong px-2 text-13 font-medium whitespace-nowrap text-sui-ink-muted outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-ink-muted hover:text-sui-ink-body focus-visible:sui-ring data-[state=open]:border-solid data-[state=open]:border-sui-accent-solid data-[state=open]:text-sui-accent data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <FilterGlyph name=\"plus\" />\n {{ label }}\n </PopoverTrigger>\n <PopoverPortal>\n <PopoverContent\n align=\"start\"\n :aria-label=\"$slots.trigger ? searchPlaceholder : undefined\"\n class=\"z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in\"\n :data-sui-panel=\"custom.panelKey\"\n :side-offset=\"8\"\n @close-auto-focus=\"custom.returnFocus\"\n @interact-outside=\"custom.ignoreTrigger\"\n @keydown=\"onKeydown\"\n @pointermove=\"keyboard = false\"\n >\n <ListboxRoot highlight-on-hover @update:model-value=\"pick\">\n <FilterFrame\n :close-label=\"closeLabel\"\n :enter-label=\"addLabel\"\n :status=\"status ?? fieldsLabel.replace('{count}', String(fields.length))\"\n >\n <div class=\"flex h-11 items-center gap-2 border-b border-sui-line-subtle px-3.5 text-sui-ink-muted\">\n <FilterGlyph class=\"size-4\" name=\"search\" />\n <ListboxFilter\n v-model=\"query\"\n :aria-label=\"searchPlaceholder\"\n auto-focus\n class=\"h-full min-w-0 flex-1 border-none bg-transparent p-0 text-sm text-sui-ink shadow-none outline-hidden placeholder:text-sui-ink-faint focus:border-none focus:shadow-none focus:ring-0 focus:outline-hidden\"\n :placeholder=\"searchPlaceholder\"\n />\n </div>\n <ListboxContent\n :aria-label=\"searchPlaceholder\"\n class=\"group/list max-h-64 overflow-auto px-1.5 pt-1 pb-1.5 outline-hidden\"\n :data-keyboard=\"keyboard || undefined\"\n >\n <ListboxGroup v-for=\"group in groups\" :key=\"group.name\">\n <ListboxGroupLabel\n v-if=\"group.name\"\n class=\"m-0 px-2 pt-2.5 pb-1 text-11 font-semibold tracking-caps text-sui-ink-muted uppercase\"\n >\n {{ group.name }}\n </ListboxGroupLabel>\n <ListboxItem\n v-for=\"field in group.fields\"\n :key=\"field.name\"\n class=\"flex min-h-8 cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-13.5 text-sui-ink outline-hidden select-none data-highlighted:bg-sui-sunken group-data-keyboard/list:data-highlighted:sui-ring-inset\"\n :value=\"field.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md bg-sui-sunken text-sui-ink-body\"\n >\n <FilterGlyph :name=\"field.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ field.label }}</span>\n <span\n v-if=\"inUse.includes(field.name)\"\n class=\"inline-flex items-center gap-1.5 text-xs font-medium text-sui-accent\"\n >\n <span class=\"size-1.5 rounded-full bg-sui-accent-solid\" />\n {{ inUseLabel }}\n </span>\n </ListboxItem>\n </ListboxGroup>\n <p v-if=\"!groups.length\" class=\"m-0 px-2 py-3 text-13 text-sui-ink-body\">\n {{ noMatchLabel.replace('{query}', query) }}\n </p>\n </ListboxContent>\n </FilterFrame>\n </ListboxRoot>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import { type FilterTriggerProps } from './trigger';
1
2
  import type { FilterField } from './types';
2
3
  export interface FilterMenuProps {
3
4
  fields: FilterField[];
@@ -5,6 +6,8 @@ export interface FilterMenuProps {
5
6
  inUse?: string[];
6
7
  /** chip: the dashed "+ Filter" in the view bar. button: the page header's Filters button, tinted while filters are in use. */
7
8
  as?: 'chip' | 'button';
9
+ /** as="button" only: ghost for a page header. Secondary by default, tinted while filters are in use. */
10
+ variant?: 'secondary' | 'ghost' | 'tinted';
8
11
  /** The footer's status; "{count} fields" by default. */
9
12
  status?: string;
10
13
  label?: string;
@@ -19,17 +22,27 @@ export interface FilterMenuProps {
19
22
  noMatchLabel?: string;
20
23
  }
21
24
  type __VLS_Props = FilterMenuProps;
25
+ type __VLS_Slots = {
26
+ /** Your own opener in place of the chip or button: spread `props` on it. `count` is the filters in use. */
27
+ trigger?: (props: {
28
+ open: boolean;
29
+ toggle: () => void;
30
+ count: number;
31
+ props: FilterTriggerProps;
32
+ }) => unknown;
33
+ };
22
34
  type __VLS_ModelProps = {
23
35
  'open'?: boolean;
24
36
  };
25
37
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
26
- declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
38
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
27
39
  pick: (name: string) => any;
28
40
  "update:open": (value: boolean) => any;
29
41
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
30
42
  onPick?: ((name: string) => any) | undefined;
31
43
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
32
44
  }>, {
45
+ variant: "secondary" | "tinted" | "ghost";
33
46
  as: "button" | "chip";
34
47
  label: string;
35
48
  closeLabel: string;
@@ -42,5 +55,11 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
42
55
  fieldsLabel: string;
43
56
  noMatchLabel: string;
44
57
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
58
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
45
59
  declare const _default: typeof __VLS_export;
46
60
  export default _default;
61
+ type __VLS_WithSlots<T, S> = T & {
62
+ new (): {
63
+ $slots: S;
64
+ };
65
+ };
@@ -1,22 +1,24 @@
1
1
  import e from "../Button/Button.js";
2
2
  import t from "./FilterFrame.js";
3
3
  import n from "./FilterGlyph.js";
4
- import { Fragment as r, computed as i, createBlock as a, createCommentVNode as o, createElementBlock as s, createElementVNode as c, createTextVNode as l, createVNode as u, defineComponent as d, mergeModels as f, mergeProps as p, openBlock as m, ref as h, renderList as g, toDisplayString as _, unref as v, useAttrs as y, useModel as b, withCtx as x } from "vue";
5
- import { ListboxContent as S, ListboxFilter as C, ListboxGroup as w, ListboxGroupLabel as T, ListboxItem as E, ListboxRoot as D, PopoverContent as O, PopoverPortal as k, PopoverRoot as A, PopoverTrigger as j } from "reka-ui";
4
+ import { useCustomTrigger as r } from "./trigger.js";
5
+ import { Fragment as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, mergeModels as p, mergeProps as m, openBlock as h, ref as g, renderList as _, renderSlot as v, toDisplayString as y, unref as b, useAttrs as x, useModel as S, withCtx as C } from "vue";
6
+ import { ListboxContent as w, ListboxFilter as T, ListboxGroup as E, ListboxGroupLabel as D, ListboxItem as O, ListboxRoot as k, PopoverAnchor as A, PopoverContent as j, PopoverPortal as M, PopoverRoot as N, PopoverTrigger as P } from "reka-ui";
6
7
  //#region src/components/Filters/FilterMenu.vue?vue&type=script&setup=true&lang.ts
7
- var M = { class: "flex h-11 items-center gap-2 border-b border-sui-line-subtle px-3.5 text-sui-ink-muted" }, N = { class: "flex size-6 shrink-0 items-center justify-center rounded-md bg-sui-sunken text-sui-ink-body" }, P = { class: "min-w-0 flex-1 truncate" }, F = {
8
+ var F = { class: "flex h-11 items-center gap-2 border-b border-sui-line-subtle px-3.5 text-sui-ink-muted" }, I = { class: "flex size-6 shrink-0 items-center justify-center rounded-md bg-sui-sunken text-sui-ink-body" }, L = { class: "min-w-0 flex-1 truncate" }, R = {
8
9
  key: 0,
9
10
  class: "inline-flex items-center gap-1.5 text-xs font-medium text-sui-accent"
10
- }, I = {
11
+ }, z = {
11
12
  key: 0,
12
13
  class: "m-0 px-2 py-3 text-13 text-sui-ink-body"
13
- }, L = /*@__PURE__*/ d({
14
+ }, B = /*@__PURE__*/ f({
14
15
  inheritAttrs: !1,
15
16
  __name: "FilterMenu",
16
- props: /*@__PURE__*/ f({
17
+ props: /*@__PURE__*/ p({
17
18
  fields: {},
18
19
  inUse: { default: () => [] },
19
20
  as: { default: "chip" },
21
+ variant: { default: void 0 },
20
22
  status: { default: void 0 },
21
23
  label: { default: "Filter" },
22
24
  buttonLabel: { default: "Filters" },
@@ -33,108 +35,123 @@ var M = { class: "flex h-11 items-center gap-2 border-b border-sui-line-subtle p
33
35
  },
34
36
  openModifiers: {}
35
37
  }),
36
- emits: /*@__PURE__*/ f(["pick"], ["update:open"]),
37
- setup(d, { emit: f }) {
38
- let L = d, R = f, z = b(d, "open"), B = y(), V = h(""), H = h(!1), U = i(() => {
39
- let e = V.value.trim().toLowerCase(), t = L.fields.filter((t) => !e || t.label.toLowerCase().includes(e));
38
+ emits: /*@__PURE__*/ p(["pick"], ["update:open"]),
39
+ setup(f, { emit: p }) {
40
+ let B = f, V = p, H = S(f, "open"), U = x(), W = r(H), G = g(""), K = g(!1), q = a(() => {
41
+ let e = G.value.trim().toLowerCase(), t = B.fields.filter((t) => !e || t.label.toLowerCase().includes(e));
40
42
  return [...new Set(t.map((e) => e.group ?? ""))].map((e) => ({
41
43
  name: e,
42
44
  fields: t.filter((t) => (t.group ?? "") === e)
43
45
  }));
44
46
  });
45
- function W(e) {
46
- typeof e == "string" && (z.value = !1, V.value = "", R("pick", e));
47
+ function J(e) {
48
+ typeof e == "string" && (H.value = !1, G.value = "", V("pick", e));
47
49
  }
48
- function G(e) {
49
- e || (V.value = "");
50
+ function Y(e) {
51
+ e || (G.value = "");
50
52
  }
51
- function K(e) {
53
+ function X(e) {
52
54
  [
53
55
  "ArrowUp",
54
56
  "ArrowDown",
55
57
  "Home",
56
58
  "End"
57
- ].includes(e.key) && (H.value = !0);
59
+ ].includes(e.key) && (K.value = !0);
58
60
  }
59
- return (i, f) => (m(), a(v(A), {
60
- open: z.value,
61
- "onUpdate:open": [f[2] ||= (e) => z.value = e, G]
61
+ return (r, a) => (h(), o(b(N), {
62
+ open: H.value,
63
+ "onUpdate:open": [a[2] ||= (e) => H.value = e, Y]
62
64
  }, {
63
- default: x(() => [d.as === "button" ? (m(), a(v(j), {
65
+ default: C(() => [r.$slots.trigger ? (h(), o(b(A), {
64
66
  key: 0,
65
67
  "as-child": ""
66
68
  }, {
67
- default: x(() => [u(e, p(v(B), { variant: d.inUse.length ? "tinted" : "secondary" }), {
68
- default: x(() => [f[3] ||= c("svg", {
69
+ default: C(() => [v(r.$slots, "trigger", {
70
+ count: f.inUse.length,
71
+ open: H.value,
72
+ props: b(W).props.value,
73
+ toggle: b(W).toggle
74
+ })]),
75
+ _: 3
76
+ })) : f.as === "button" ? (h(), o(b(P), {
77
+ key: 1,
78
+ "as-child": ""
79
+ }, {
80
+ default: C(() => [d(e, m(b(U), { variant: f.variant ?? (f.inUse.length ? "tinted" : "secondary") }), {
81
+ default: C(() => [a[3] ||= l("svg", {
69
82
  "aria-hidden": "true",
70
83
  class: "size-4 fill-none stroke-current",
71
84
  "stroke-linejoin": "round",
72
85
  "stroke-width": "1.5",
73
86
  viewBox: "0 0 16 16"
74
- }, [c("path", { d: "M2.5 3.5h11l-4.25 5v4l-2.5 1v-5z" })], -1), l(" " + _(d.buttonLabel), 1)]),
87
+ }, [l("path", { d: "M2.5 3.5h11l-4.25 5v4l-2.5 1v-5z" })], -1), u(" " + y(f.buttonLabel), 1)]),
75
88
  _: 1
76
89
  }, 16, ["variant"])]),
77
90
  _: 1
78
- })) : (m(), a(v(j), p({ key: 1 }, v(B), { class: "inline-flex h-7.5 items-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong px-2 text-13 font-medium whitespace-nowrap text-sui-ink-muted outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-ink-muted hover:text-sui-ink-body focus-visible:sui-ring data-[state=open]:border-solid data-[state=open]:border-sui-accent-solid data-[state=open]:text-sui-accent data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]" }), {
79
- default: x(() => [u(n, { name: "plus" }), l(" " + _(d.label), 1)]),
91
+ })) : (h(), o(b(P), m({ key: 2 }, b(U), { class: "inline-flex h-7.5 items-center gap-1.5 rounded-lg border border-dashed border-sui-line-strong px-2 text-13 font-medium whitespace-nowrap text-sui-ink-muted outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-ink-muted hover:text-sui-ink-body focus-visible:sui-ring data-[state=open]:border-solid data-[state=open]:border-sui-accent-solid data-[state=open]:text-sui-accent data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]" }), {
92
+ default: C(() => [d(n, { name: "plus" }), u(" " + y(f.label), 1)]),
80
93
  _: 1
81
- }, 16)), u(v(k), null, {
82
- default: x(() => [u(v(O), {
94
+ }, 16)), d(b(M), null, {
95
+ default: C(() => [d(b(j), {
83
96
  align: "start",
97
+ "aria-label": r.$slots.trigger ? f.searchPlaceholder : void 0,
84
98
  class: "z-[1100] w-85 max-w-[calc(100vw-2rem)] origin-(--reka-popover-content-transform-origin) rounded-xl border border-sui-line bg-sui-surface text-sui-ink shadow-lg data-[state=open]:animate-sui-overlay-in",
99
+ "data-sui-panel": b(W).panelKey,
85
100
  "side-offset": 8,
86
- onKeydown: K,
87
- onPointermove: f[1] ||= (e) => H.value = !1
101
+ onCloseAutoFocus: b(W).returnFocus,
102
+ onInteractOutside: b(W).ignoreTrigger,
103
+ onKeydown: X,
104
+ onPointermove: a[1] ||= (e) => K.value = !1
88
105
  }, {
89
- default: x(() => [u(v(D), {
106
+ default: C(() => [d(b(k), {
90
107
  "highlight-on-hover": "",
91
- "onUpdate:modelValue": W
108
+ "onUpdate:modelValue": J
92
109
  }, {
93
- default: x(() => [u(t, {
94
- "close-label": d.closeLabel,
95
- "enter-label": d.addLabel,
96
- status: d.status ?? d.fieldsLabel.replace("{count}", String(d.fields.length))
110
+ default: C(() => [d(t, {
111
+ "close-label": f.closeLabel,
112
+ "enter-label": f.addLabel,
113
+ status: f.status ?? f.fieldsLabel.replace("{count}", String(f.fields.length))
97
114
  }, {
98
- default: x(() => [c("div", M, [u(n, {
115
+ default: C(() => [l("div", F, [d(n, {
99
116
  class: "size-4",
100
117
  name: "search"
101
- }), u(v(C), {
102
- modelValue: V.value,
103
- "onUpdate:modelValue": f[0] ||= (e) => V.value = e,
104
- "aria-label": d.searchPlaceholder,
118
+ }), d(b(T), {
119
+ modelValue: G.value,
120
+ "onUpdate:modelValue": a[0] ||= (e) => G.value = e,
121
+ "aria-label": f.searchPlaceholder,
105
122
  "auto-focus": "",
106
123
  class: "h-full min-w-0 flex-1 border-none bg-transparent p-0 text-sm text-sui-ink shadow-none outline-hidden placeholder:text-sui-ink-faint focus:border-none focus:shadow-none focus:ring-0 focus:outline-hidden",
107
- placeholder: d.searchPlaceholder
124
+ placeholder: f.searchPlaceholder
108
125
  }, null, 8, [
109
126
  "modelValue",
110
127
  "aria-label",
111
128
  "placeholder"
112
- ])]), u(v(S), {
113
- "aria-label": d.searchPlaceholder,
129
+ ])]), d(b(w), {
130
+ "aria-label": f.searchPlaceholder,
114
131
  class: "group/list max-h-64 overflow-auto px-1.5 pt-1 pb-1.5 outline-hidden",
115
- "data-keyboard": H.value || void 0
132
+ "data-keyboard": K.value || void 0
116
133
  }, {
117
- default: x(() => [(m(!0), s(r, null, g(U.value, (e) => (m(), a(v(w), { key: e.name }, {
118
- default: x(() => [e.name ? (m(), a(v(T), {
134
+ default: C(() => [(h(!0), c(i, null, _(q.value, (e) => (h(), o(b(E), { key: e.name }, {
135
+ default: C(() => [e.name ? (h(), o(b(D), {
119
136
  key: 0,
120
137
  class: "m-0 px-2 pt-2.5 pb-1 text-11 font-semibold tracking-caps text-sui-ink-muted uppercase"
121
138
  }, {
122
- default: x(() => [l(_(e.name), 1)]),
139
+ default: C(() => [u(y(e.name), 1)]),
123
140
  _: 2
124
- }, 1024)) : o("", !0), (m(!0), s(r, null, g(e.fields, (e) => (m(), a(v(E), {
141
+ }, 1024)) : s("", !0), (h(!0), c(i, null, _(e.fields, (e) => (h(), o(b(O), {
125
142
  key: e.name,
126
143
  class: "flex min-h-8 cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1 text-13.5 text-sui-ink outline-hidden select-none data-highlighted:bg-sui-sunken group-data-keyboard/list:data-highlighted:sui-ring-inset",
127
144
  value: e.name
128
145
  }, {
129
- default: x(() => [
130
- c("span", N, [u(n, { name: e.type }, null, 8, ["name"])]),
131
- c("span", P, _(e.label), 1),
132
- d.inUse.includes(e.name) ? (m(), s("span", F, [f[4] ||= c("span", { class: "size-1.5 rounded-full bg-sui-accent-solid" }, null, -1), l(" " + _(d.inUseLabel), 1)])) : o("", !0)
146
+ default: C(() => [
147
+ l("span", I, [d(n, { name: e.type }, null, 8, ["name"])]),
148
+ l("span", L, y(e.label), 1),
149
+ f.inUse.includes(e.name) ? (h(), c("span", R, [a[4] ||= l("span", { class: "size-1.5 rounded-full bg-sui-accent-solid" }, null, -1), u(" " + y(f.inUseLabel), 1)])) : s("", !0)
133
150
  ]),
134
151
  _: 2
135
152
  }, 1032, ["value"]))), 128))]),
136
153
  _: 2
137
- }, 1024))), 128)), U.value.length ? o("", !0) : (m(), s("p", I, _(d.noMatchLabel.replace("{query}", V.value)), 1))]),
154
+ }, 1024))), 128)), q.value.length ? s("", !0) : (h(), c("p", z, y(f.noMatchLabel.replace("{query}", G.value)), 1))]),
138
155
  _: 1
139
156
  }, 8, ["aria-label", "data-keyboard"])]),
140
157
  _: 1
@@ -146,14 +163,19 @@ var M = { class: "flex h-11 items-center gap-2 border-b border-sui-line-subtle p
146
163
  _: 1
147
164
  })]),
148
165
  _: 1
149
- })]),
166
+ }, 8, [
167
+ "aria-label",
168
+ "data-sui-panel",
169
+ "onCloseAutoFocus",
170
+ "onInteractOutside"
171
+ ])]),
150
172
  _: 1
151
173
  })]),
152
- _: 1
174
+ _: 3
153
175
  }, 8, ["open"]));
154
176
  }
155
177
  });
156
178
  //#endregion
157
- export { L as default };
179
+ export { B as default };
158
180
 
159
181
  //# sourceMappingURL=FilterMenu.vue_vue_type_script_setup_true_lang.js.map