@sparklingopinions/sparkling-ui 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Board/Board.js.map +1 -1
- package/dist/components/Board/Board.vue.d.ts +6 -2
- package/dist/components/Board/Board.vue_vue_type_script_setup_true_lang.js +142 -74
- package/dist/components/Board/Board.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/FilterChip.js.map +1 -1
- package/dist/components/Filters/FilterChip.vue.d.ts +4 -1
- package/dist/components/Filters/FilterChip.vue_vue_type_script_setup_true_lang.js +29 -24
- package/dist/components/Filters/FilterChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/SortMenu.js.map +1 -1
- package/dist/components/Filters/SortMenu.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/Filters/SortMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Filters/index.d.ts +1 -1
- package/dist/components/Filters/types.d.ts +8 -0
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/Popover.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/Popover/Popover.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/components/Table/Table.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/Table/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import e from "../Icon/Icon.js";
|
|
2
2
|
import t from "../Checkbox/Checkbox.js";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
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),
|
|
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
|
-
}) : ""),
|
|
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(""),
|
|
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
|
|
96
|
+
function be(e) {
|
|
92
97
|
G.value = $.value.includes(e) ? $.value.filter((t) => t !== e) : [...$.value, e];
|
|
93
98
|
}
|
|
94
|
-
function
|
|
99
|
+
function xe() {
|
|
95
100
|
K.value = !1, g.onRemove?.();
|
|
96
101
|
}
|
|
97
|
-
let
|
|
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(
|
|
129
|
-
|
|
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(
|
|
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(
|
|
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:
|
|
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 }, [
|
|
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(
|
|
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) =>
|
|
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",
|
|
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(
|
|
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(
|
|
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(
|
|
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":"SortMenu.js","names":["_sfc_main","SortMenu_vue_vue_type_script_setup_true_lang_default","SortMenu_default"],"sources":["../../../src/components/Filters/SortMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger, RadioGroupItem, RadioGroupRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport SortArrow from './SortArrow.vue'\nimport { sortDirections } from './defaults'\nimport type { FilterField, FilterFieldType, ViewSort } from './types'\n\nexport interface SortMenuProps {\n /** The sortable fields. */\n options: FilterField[]\n /** chip: the sort in the view bar, which shows only while there is one. button: the page header's Sort button. */\n as?: 'chip' | 'button'\n /** Boards can't sort: disable the button, with a Tooltip saying why. */\n disabled?: boolean\n status?: string\n /** The two directions' words for each field type, ascending first. */\n directionLabels?: Partial<Record<FilterFieldType, [string, string]>>\n title?: string\n buttonLabel?: string\n clearLabel?: string\n directionLabel?: string\n doneLabel?: string\n closeLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SortMenuProps>(), {\n as: 'chip',\n status: undefined,\n directionLabels: () => ({}),\n title: 'Sort by',\n buttonLabel: 'Sort',\n clearLabel: 'Clear sort',\n directionLabel: 'Direction',\n doneLabel: 'Done',\n closeLabel: 'Close'\n})\n\nconst sort = defineModel<ViewSort | null>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\nconst attrs = useAttrs()\n\nconst current = computed(() => (sort.value ? props.options.find((o) => o.name === sort.value!.name) : undefined))\nconst words = (type: FilterFieldType) => props.directionLabels[type] ?? sortDirections[type]\nconst dirLabel = computed(() => (current.value ? words(current.value.type)[sort.value!.dir === 'desc' ? 1 : 0] : ''))\n\nfunction pickField(name: string) {\n sort.value = { name, dir: sort.value?.name === name ? sort.value.dir : 'asc' }\n}\n\nfunction clear() {\n sort.value = null\n open.value = false\n}\n\nconst row =\n 'flex min-h-9 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'\n</script>\n\n<!-- A view's sort: the header's Sort button or the view bar's chip (\"Name, A → Z\") open a panel of fields and a direction. -->\n<template>\n <PopoverRoot v-if=\"as === 'button' || current\" v-model:open=\"open\">\n <PopoverTrigger v-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :disabled=\"disabled\" :variant=\"current ? 'tinted' : 'secondary'\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\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-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-13 whitespace-nowrap text-sui-accent outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-accent-bright focus-visible:sui-ring data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <SortArrow :dir=\"sort!.dir\" />\n <span\n ><span class=\"font-medium\">{{ current!.label }},</span>{{ ' ' }}{{ dirLabel }}</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 <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n <span class=\"text-sm font-semibold text-sui-ink\">{{ title }}</span>\n <button\n v-if=\"current\"\n class=\"ml-auto inline-flex h-7 items-center rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-sunken hover:text-sui-ink focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"clear\"\n >\n {{ clearLabel }}\n </button>\n </div>\n <RadioGroupRoot\n :aria-label=\"title\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"sort?.name\"\n @update:model-value=\"pickField($event as string)\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.name\"\n :class=\"[\n row,\n option.name === sort?.name\n ? 'bg-sui-accent-wash font-semibold text-sui-accent'\n : 'text-sui-ink hover:bg-sui-sunken'\n ]\"\n :value=\"option.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md\"\n :class=\"\n option.name === sort?.name ? 'bg-sui-surface text-sui-accent' : 'bg-sui-sunken text-sui-ink-body'\n \"\n >\n <FilterGlyph :name=\"option.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <CheckIcon v-if=\"option.name === sort?.name\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <RadioGroupRoot\n v-if=\"current\"\n :aria-label=\"directionLabel\"\n class=\"mx-3 mb-3 grid grid-cols-2 gap-0.5 rounded-lg bg-sui-sunken p-0.75\"\n :model-value=\"sort!.dir\"\n orientation=\"horizontal\"\n @update:model-value=\"sort = { name: sort!.name, dir: $event as ViewSort['dir'] }\"\n >\n <RadioGroupItem\n v-for=\"(dir, i) in ['asc', 'desc'] as const\"\n :key=\"dir\"\n class=\"flex h-9 items-center justify-center gap-1.5 rounded-md text-13 font-medium outline-hidden transition-colors duration-150 focus-visible:sui-ring-inset\"\n :class=\"\n sort!.dir === dir\n ? 'bg-sui-surface text-sui-ink shadow-(--sui-shadow-raised) ring-1 ring-sui-line-subtle'\n : 'text-sui-ink-body hover:text-sui-ink'\n \"\n :value=\"dir\"\n >\n <SortArrow :dir=\"dir\" />\n {{ words(current.type)[i] }}\n </RadioGroupItem>\n </RadioGroupRoot>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"SortMenu.js","names":["_sfc_main","SortMenu_vue_vue_type_script_setup_true_lang_default","SortMenu_default"],"sources":["../../../src/components/Filters/SortMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger, RadioGroupItem, RadioGroupRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport SortArrow from './SortArrow.vue'\nimport { sortDirections } from './defaults'\nimport type { FilterField, FilterFieldType, ViewSort } from './types'\n\nexport interface SortMenuProps {\n /** The sortable fields. */\n options: FilterField[]\n /** chip: the sort in the view bar, which shows only while there is one. button: the page header's Sort button. */\n as?: 'chip' | 'button'\n /** Boards can't sort: disable the button, with a Tooltip saying why. */\n disabled?: boolean\n status?: string\n /** The two directions' words for each field type, ascending first. */\n directionLabels?: Partial<Record<FilterFieldType, [string, string]>>\n title?: string\n buttonLabel?: string\n clearLabel?: string\n directionLabel?: string\n doneLabel?: string\n closeLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SortMenuProps>(), {\n as: 'chip',\n status: undefined,\n directionLabels: () => ({}),\n title: 'Sort by',\n buttonLabel: 'Sort',\n clearLabel: 'Clear sort',\n directionLabel: 'Direction',\n doneLabel: 'Done',\n closeLabel: 'Close'\n})\n\nconst sort = defineModel<ViewSort | null>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\nconst attrs = useAttrs()\n\nconst current = computed(() => (sort.value ? props.options.find((o) => o.name === sort.value!.name) : undefined))\nconst words = (type: FilterFieldType) => props.directionLabels[type] ?? sortDirections[type]\nconst dirLabel = computed(() => (current.value ? words(current.value.type)[sort.value!.dir === 'desc' ? 1 : 0] : ''))\n\nfunction pickField(name: string) {\n const field = props.options.find((o) => o.name === name)\n sort.value = { name, dir: sort.value?.name === name ? sort.value.dir : (field?.sortDir ?? 'asc') }\n}\n\nfunction clear() {\n sort.value = null\n open.value = false\n}\n\nconst row =\n 'flex min-h-9 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'\n</script>\n\n<!-- A view's sort: the header's Sort button or the view bar's chip (\"Name, A → Z\") open a panel of fields and a direction. -->\n<template>\n <PopoverRoot v-if=\"as === 'button' || current\" v-model:open=\"open\">\n <PopoverTrigger v-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :disabled=\"disabled\" :variant=\"current ? 'tinted' : 'secondary'\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\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-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-13 whitespace-nowrap text-sui-accent outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-accent-bright focus-visible:sui-ring data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <SortArrow :dir=\"sort!.dir\" />\n <span\n ><span class=\"font-medium\">{{ current!.label }},</span>{{ ' ' }}{{ dirLabel }}</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 <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n <span class=\"text-sm font-semibold text-sui-ink\">{{ title }}</span>\n <button\n v-if=\"current\"\n class=\"ml-auto inline-flex h-7 items-center rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-sunken hover:text-sui-ink focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"clear\"\n >\n {{ clearLabel }}\n </button>\n </div>\n <RadioGroupRoot\n :aria-label=\"title\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"sort?.name\"\n @update:model-value=\"pickField($event as string)\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.name\"\n :class=\"[\n row,\n option.name === sort?.name\n ? 'bg-sui-accent-wash font-semibold text-sui-accent'\n : 'text-sui-ink hover:bg-sui-sunken'\n ]\"\n :value=\"option.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md\"\n :class=\"\n option.name === sort?.name ? 'bg-sui-surface text-sui-accent' : 'bg-sui-sunken text-sui-ink-body'\n \"\n >\n <FilterGlyph :name=\"option.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <CheckIcon v-if=\"option.name === sort?.name\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <RadioGroupRoot\n v-if=\"current\"\n :aria-label=\"directionLabel\"\n class=\"mx-3 mb-3 grid grid-cols-2 gap-0.5 rounded-lg bg-sui-sunken p-0.75\"\n :model-value=\"sort!.dir\"\n orientation=\"horizontal\"\n @update:model-value=\"sort = { name: sort!.name, dir: $event as ViewSort['dir'] }\"\n >\n <RadioGroupItem\n v-for=\"(dir, i) in ['asc', 'desc'] as const\"\n :key=\"dir\"\n class=\"flex h-9 items-center justify-center gap-1.5 rounded-md text-13 font-medium outline-hidden transition-colors duration-150 focus-visible:sui-ring-inset\"\n :class=\"\n sort!.dir === dir\n ? 'bg-sui-surface text-sui-ink shadow-(--sui-shadow-raised) ring-1 ring-sui-line-subtle'\n : 'text-sui-ink-body hover:text-sui-ink'\n \"\n :value=\"dir\"\n >\n <SortArrow :dir=\"dir\" />\n {{ words(current.type)[i] }}\n </RadioGroupItem>\n </RadioGroupRoot>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
|
|
@@ -35,9 +35,10 @@ var j = { class: "font-medium" }, M = { class: "flex h-11 items-center gap-1.5 p
|
|
|
35
35
|
setup(m) {
|
|
36
36
|
let h = m, I = C(m, "modelValue"), L = C(m, "open"), R = S(), z = s(() => I.value ? h.options.find((e) => e.name === I.value.name) : void 0), B = (e) => h.directionLabels[e] ?? i[e], V = s(() => z.value ? B(z.value.type)[+(I.value.dir === "desc")] : "");
|
|
37
37
|
function H(e) {
|
|
38
|
+
let t = h.options.find((t) => t.name === e);
|
|
38
39
|
I.value = {
|
|
39
40
|
name: e,
|
|
40
|
-
dir: I.value?.name === e ? I.value.dir : "asc"
|
|
41
|
+
dir: I.value?.name === e ? I.value.dir : t?.sortDir ?? "asc"
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
44
|
function U() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortMenu.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","_unref","_withCtx","_createVNode","Button","_mergeProps","_createElementVNode","_createTextVNode","_toDisplayString","SortArrow","FilterFrame","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_normalizeClass","FilterGlyph","CheckIcon","Button_default","CheckIcon_default","FilterFrame_default","FilterGlyph_default","SortArrow_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","row","SortMenu_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","sort","useModel","open","attrs","useAttrs","current","computed","o","words","type","sortDirections","dirLabel","pickField","name","clear","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","PopoverTrigger","createVNode","mergeProps","createElementVNode","createTextVNode","toDisplayString","PopoverPortal","PopoverContent","createElementBlock","createCommentVNode","RadioGroupRoot","Fragment","renderList","RadioGroupItem","option","normalizeClass","dir","i"],"sources":["../../../src/components/Filters/SortMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger, RadioGroupItem, RadioGroupRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport SortArrow from './SortArrow.vue'\nimport { sortDirections } from './defaults'\nimport type { FilterField, FilterFieldType, ViewSort } from './types'\n\nexport interface SortMenuProps {\n /** The sortable fields. */\n options: FilterField[]\n /** chip: the sort in the view bar, which shows only while there is one. button: the page header's Sort button. */\n as?: 'chip' | 'button'\n /** Boards can't sort: disable the button, with a Tooltip saying why. */\n disabled?: boolean\n status?: string\n /** The two directions' words for each field type, ascending first. */\n directionLabels?: Partial<Record<FilterFieldType, [string, string]>>\n title?: string\n buttonLabel?: string\n clearLabel?: string\n directionLabel?: string\n doneLabel?: string\n closeLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SortMenuProps>(), {\n as: 'chip',\n status: undefined,\n directionLabels: () => ({}),\n title: 'Sort by',\n buttonLabel: 'Sort',\n clearLabel: 'Clear sort',\n directionLabel: 'Direction',\n doneLabel: 'Done',\n closeLabel: 'Close'\n})\n\nconst sort = defineModel<ViewSort | null>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\nconst attrs = useAttrs()\n\nconst current = computed(() => (sort.value ? props.options.find((o) => o.name === sort.value!.name) : undefined))\nconst words = (type: FilterFieldType) => props.directionLabels[type] ?? sortDirections[type]\nconst dirLabel = computed(() => (current.value ? words(current.value.type)[sort.value!.dir === 'desc' ? 1 : 0] : ''))\n\nfunction pickField(name: string) {\n sort.value = { name, dir: sort.value?.name === name ? sort.value.dir : 'asc' }\n}\n\nfunction clear() {\n sort.value = null\n open.value = false\n}\n\nconst row =\n 'flex min-h-9 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'\n</script>\n\n<!-- A view's sort: the header's Sort button or the view bar's chip (\"Name, A → Z\") open a panel of fields and a direction. -->\n<template>\n <PopoverRoot v-if=\"as === 'button' || current\" v-model:open=\"open\">\n <PopoverTrigger v-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :disabled=\"disabled\" :variant=\"current ? 'tinted' : 'secondary'\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\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-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-13 whitespace-nowrap text-sui-accent outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-accent-bright focus-visible:sui-ring data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <SortArrow :dir=\"sort!.dir\" />\n <span\n ><span class=\"font-medium\">{{ current!.label }},</span>{{ ' ' }}{{ dirLabel }}</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 <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n <span class=\"text-sm font-semibold text-sui-ink\">{{ title }}</span>\n <button\n v-if=\"current\"\n class=\"ml-auto inline-flex h-7 items-center rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-sunken hover:text-sui-ink focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"clear\"\n >\n {{ clearLabel }}\n </button>\n </div>\n <RadioGroupRoot\n :aria-label=\"title\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"sort?.name\"\n @update:model-value=\"pickField($event as string)\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.name\"\n :class=\"[\n row,\n option.name === sort?.name\n ? 'bg-sui-accent-wash font-semibold text-sui-accent'\n : 'text-sui-ink hover:bg-sui-sunken'\n ]\"\n :value=\"option.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md\"\n :class=\"\n option.name === sort?.name ? 'bg-sui-surface text-sui-accent' : 'bg-sui-sunken text-sui-ink-body'\n \"\n >\n <FilterGlyph :name=\"option.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <CheckIcon v-if=\"option.name === sort?.name\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <RadioGroupRoot\n v-if=\"current\"\n :aria-label=\"directionLabel\"\n class=\"mx-3 mb-3 grid grid-cols-2 gap-0.5 rounded-lg bg-sui-sunken p-0.75\"\n :model-value=\"sort!.dir\"\n orientation=\"horizontal\"\n @update:model-value=\"sort = { name: sort!.name, dir: $event as ViewSort['dir'] }\"\n >\n <RadioGroupItem\n v-for=\"(dir, i) in ['asc', 'desc'] as const\"\n :key=\"dir\"\n class=\"flex h-9 items-center justify-center gap-1.5 rounded-md text-13 font-medium outline-hidden transition-colors duration-150 focus-visible:sui-ring-inset\"\n :class=\"\n sort!.dir === dir\n ? 'bg-sui-surface text-sui-ink shadow-(--sui-shadow-raised) ring-1 ring-sui-line-subtle'\n : 'text-sui-ink-body hover:text-sui-ink'\n \"\n :value=\"dir\"\n >\n <SortArrow :dir=\"dir\" />\n {{ words(current.type)[i] }}\n </RadioGroupItem>\n </RadioGroupRoot>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":";;;;;;;;;A,mNA+DM6B,IACJ,+K;;;;;;;;;;;;;;;;;;;;;;;;;;EA/BF,IAAMM,IAAQC,GAYRC,IAAOrC,EAA4BoC,GAAA,YAAkB,GACrDG,IAAOvC,EAAoBoC,GAAC,MAA0B,GAEtDI,IAAQC,EAAS,GAEjBC,IAAUC,QAAgBN,EAAK,QAAQF,EAAM,QAAQ,MAAM,MAAMS,EAAE,SAASP,EAAK,MAAO,IAAI,IAAI,KAAA,CAAU,GAC1GQ,KAAS,MAA0BV,EAAM,gBAAgBW,MAASC,EAAeD,IACjFE,IAAWL,QAAgBD,EAAQ,QAAQG,EAAMH,EAAQ,MAAM,IAAI,CAAC,CAAC,IAAK,MAAO,QAAQ,WAAkB,EAAG;EAEpH,SAASO,EAAU,GAAc;GAC/B,EAAK,QAAQ;IAAE;IAAM,KAAKZ,EAAK,OAAO,SAASa,IAAOb,EAAK,MAAM,MAAM;GAAM;EAC/E;EAEA,SAASc,IAAQ;GAEf,AADA,EAAK,QAAQ,MACb,EAAK,QAAQ;EACf;E,iBAQqBf,EAAA,OAAE,YAAiBM,EAAA,SAAtCzC,EAAA,GAAAC,EAsHcC,EAAAoD,CAAA,GAAA;;GAtHyC,MAAMhB,EAAA;GAAA,iBAAA,AAAAiB,EAAA,QAAA,MAAA,EAAI,QAAAC;;GAC/D,SAAArD,QAciB,CAdKgC,EAAA,OAAE,YAAxBnC,EAAA,GAAAC,EAciBC,EAAAwD,CAAA,GAAA;;IAdsB,YAAA;;IACrC,SAAAvD,QAYS,CAZTC,EAYSC,GAZTC,EAAgBJ,EAYPqC,CAAA,GAZY;KAAG,UAAUJ,EAAA;KAAW,SAASM,EAAA,QAAO,WAAA;;KAC3D,SAAAtC,QASM,CATN,AAAAoD,EAAA,OAAAhD,EASM,OAAA;MARJ,eAAY;MACZ,OAAM;MACN,kBAAe;MACf,mBAAgB;MAChB,gBAAa;MACb,SAAQ;K,IAERA,EAAuE,QAAA,EAAjE,GAAE,6DAA4D,CAAA,C,QAChEC,EAAA,MACNC,EAAG0B,EAAA,WAAW,GAAA,CAAA,C;;;;G,OAGlBnC,EAAA,GAAAC,EAkBiBC,EAAAwD,CAAA,GAlBjBpD,EAkBiB,EAAA,KAAA,EAAA,GAhBPJ,EAAAqC,CAAA,GAAK,EACb,OAAM,4XAA2X,CAAA,GAAA;IAEjY,SAAApC,QAA8B;KAA9BC,EAA8BM,GAAA,EAAlB,KAAK0B,EAAA,MAAM,I;KACvB7B,EAEC,QAAA,MAAA,CADEA,EAAsD,QAAtDiB,GAAsDf,EAAzBgC,EAAA,MAAS,KAAK,IAAG,KAAC,CAAA,GAAUjC,EAAAC,EAAA,GAAG,IAAAA,EAAMsC,EAAA,KAAQ,GAAA,CAAA,C;KAE7E,AAAAQ,EAAA,OAAAhD,EAQM,OAAA;MAPJ,eAAY;MACZ,OAAM;MACN,kBAAe;MACf,gBAAa;MACb,SAAQ;K,IAERA,EAAyB,QAAA,EAAnB,GAAE,eAAc,CAAA,C;;;G,SAG1BH,EAkFgBF,EAAA8D,CAAA,GAAA,MAAA;IAjFd,SAAA7D,QAgFiB,CAhFjBC,EAgFiBF,EAAA+D,CAAA,GAAA;KA/Ef,OAAM;KACN,OAAM;KACL,eAAa;;KAEd,SAAA9D,QA0Ec,CA1EdC,EA0EcO,GAAA;MA1EA,eAAawB,EAAA;MAAa,eAAaA,EAAA;MAAY,QAAQA,EAAA;MAAS,SAAK,AAAAoB,EAAA,QAAA,MAAE,EAAA,QAAI;;MAC3F,SAAApD,QAoBM;OApBNI,EAoBM,OApBNkB,GAoBM;QAnBJ,AAAA8B,EAAA,OAAAhD,EASM,OAAA;SARJ,eAAY;SACZ,OAAM;SACN,kBAAe;SACf,mBAAgB;SAChB,gBAAa;SACb,SAAQ;Q,IAERA,EAAuE,QAAA,EAAjE,GAAE,6DAA4D,CAAA,C;QAEtEA,EAAmE,QAAnEmB,GAAmEjB,EAAf0B,EAAA,KAAK,GAAA,CAAA;QAEjDM,EAAA,SADRzC,EAAA,GAAAY,EAOS,UAAA;;SALP,OAAM;SACN,MAAK;SACJ,SAAOsC;QAEL,GAAAzC,EAAA0B,EAAA,UAAU,GAAA,CAAA,K;;OAGjB/B,EA4BiBF,EAAAkE,CAAA,GAAA;QA3Bd,cAAYjC,EAAA;QACb,OAAM;QACL,eAAaC,EAAA,OAAM;QACnB,uBAAkB,AAAAmB,EAAA,QAAA,MAAEP,EAAUQ,CAAM;;QAGnC,SAAArD,QAAyB,EAD3BH,EAAA,EAAA,GAAAY,EAqBiBE,GAAA,MAAAC,EApBEoB,EAAA,UAAV,OADTnC,EAAA,GAAAC,EAqBiBC,EAAAqE,CAAA,GAAA;SAnBd,KAAKC,EAAO;SACZ,OAAKxD,EAAA,CAAoBY,GAAqB4C,EAAO,SAASpC,EAAA,OAAM,O;SAMpE,OAAOoC,EAAO;;SAEf,SAAArE,QAOO;UAPPI,EAOO,QAAA,EANL,OAAKS,EAAA,CAAC,+DACqBwD,EAAO,SAASpC,EAAA,OAAM,OAAI,mCAAA,iC,OAIrDhC,EAAmCa,GAAA,EAArB,MAAMuD,EAAO,K;UAE7BjE,EAA+D,QAA/DoB,GAA+DlB,EAAtB+D,EAAO,KAAK,GAAA,CAAA;UACpCA,EAAO,SAASpC,EAAA,OAAM,QAAvCpC,EAAA,GAAAC,EAA+CiB,GAAA,EAAA,KAAA,EAAA,CAAA,K;;;;;;OAI3CuB,EAAA,SADRzC,EAAA,GAAAC,EAsBiBC,EAAAkE,CAAA,GAAA;;QApBd,cAAYjC,EAAA;QACb,OAAM;QACL,eAAaC,EAAA,MAAM;QACpB,aAAY;QACX,uBAAkB,AAAAmB,EAAA,QAAA,MAAE,EAAA,QAAI;SAAA,MAAWnB,EAAA,MAAM;SAAI,KAAOoB;QAAM;;QAGzD,SAAArD,QAA4C,EAD9CH,EAAA,GAAAY,EAaiBE,GAAA,MAAAC,EAZI,CAAA,OAAA,MAAA,IAAX,GAAK,MADfX,EAaiBF,EAAAqE,CAAA,GAAA;SAXd,KAAKG;SACN,OAAK1D,EAAA,CAAC,0JACmBoB,EAAA,MAAM,QAAQsC,I;SAKtC,OAAOA;;SAER,SAAAvE,QAAwB,CAAxBC,EAAwBM,GAAA,EAAP,OAAG,GAAA,MAAA,GAAA,CAAA,KAAA,CAAA,GAAIF,EAAA,MACxBC,EAAGmC,EAAMH,EAAA,MAAQ,IAAI,CAAA,CAAEkC,EAAC,GAAA,CAAA,C"}
|
|
1
|
+
{"version":3,"file":"SortMenu.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","_unref","_withCtx","_createVNode","Button","_mergeProps","_createElementVNode","_createTextVNode","_toDisplayString","SortArrow","FilterFrame","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_normalizeClass","FilterGlyph","CheckIcon","Button_default","CheckIcon_default","FilterFrame_default","FilterGlyph_default","SortArrow_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","row","SortMenu_vue_vue_type_script_setup_true_lang_default","\"modelValue\"","\"modelModifiers\"","\"open\"","\"openModifiers\"","props","__props","sort","useModel","open","attrs","useAttrs","current","computed","o","words","type","sortDirections","dirLabel","pickField","field","name","clear","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","PopoverTrigger","createVNode","mergeProps","createElementVNode","createTextVNode","toDisplayString","PopoverPortal","PopoverContent","createElementBlock","createCommentVNode","RadioGroupRoot","Fragment","renderList","RadioGroupItem","option","normalizeClass","dir","i"],"sources":["../../../src/components/Filters/SortMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue'\n\nimport { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger, RadioGroupItem, RadioGroupRoot } from 'reka-ui'\n\nimport Button from '../Button/Button.vue'\nimport CheckIcon from '../internal/CheckIcon.vue'\nimport FilterFrame from './FilterFrame.vue'\nimport FilterGlyph from './FilterGlyph.vue'\nimport SortArrow from './SortArrow.vue'\nimport { sortDirections } from './defaults'\nimport type { FilterField, FilterFieldType, ViewSort } from './types'\n\nexport interface SortMenuProps {\n /** The sortable fields. */\n options: FilterField[]\n /** chip: the sort in the view bar, which shows only while there is one. button: the page header's Sort button. */\n as?: 'chip' | 'button'\n /** Boards can't sort: disable the button, with a Tooltip saying why. */\n disabled?: boolean\n status?: string\n /** The two directions' words for each field type, ascending first. */\n directionLabels?: Partial<Record<FilterFieldType, [string, string]>>\n title?: string\n buttonLabel?: string\n clearLabel?: string\n directionLabel?: string\n doneLabel?: string\n closeLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<SortMenuProps>(), {\n as: 'chip',\n status: undefined,\n directionLabels: () => ({}),\n title: 'Sort by',\n buttonLabel: 'Sort',\n clearLabel: 'Clear sort',\n directionLabel: 'Direction',\n doneLabel: 'Done',\n closeLabel: 'Close'\n})\n\nconst sort = defineModel<ViewSort | null>({ default: null })\nconst open = defineModel<boolean>('open', { default: false })\n\nconst attrs = useAttrs()\n\nconst current = computed(() => (sort.value ? props.options.find((o) => o.name === sort.value!.name) : undefined))\nconst words = (type: FilterFieldType) => props.directionLabels[type] ?? sortDirections[type]\nconst dirLabel = computed(() => (current.value ? words(current.value.type)[sort.value!.dir === 'desc' ? 1 : 0] : ''))\n\nfunction pickField(name: string) {\n const field = props.options.find((o) => o.name === name)\n sort.value = { name, dir: sort.value?.name === name ? sort.value.dir : (field?.sortDir ?? 'asc') }\n}\n\nfunction clear() {\n sort.value = null\n open.value = false\n}\n\nconst row =\n 'flex min-h-9 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'\n</script>\n\n<!-- A view's sort: the header's Sort button or the view bar's chip (\"Name, A → Z\") open a panel of fields and a direction. -->\n<template>\n <PopoverRoot v-if=\"as === 'button' || current\" v-model:open=\"open\">\n <PopoverTrigger v-if=\"as === 'button'\" as-child>\n <Button v-bind=\"attrs\" :disabled=\"disabled\" :variant=\"current ? 'tinted' : 'secondary'\">\n <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\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-sui-accent-line bg-sui-accent-wash pr-1.5 pl-2 text-13 whitespace-nowrap text-sui-accent outline-hidden transition-[border-color,box-shadow] duration-150 hover:border-sui-accent-bright focus-visible:sui-ring data-[state=open]:border-sui-accent-solid data-[state=open]:shadow-[0_0_0_3px_rgb(var(--sui-focus-ring))]\"\n >\n <SortArrow :dir=\"sort!.dir\" />\n <span\n ><span class=\"font-medium\">{{ current!.label }},</span>{{ ' ' }}{{ dirLabel }}</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 <svg\n aria-hidden=\"true\"\n class=\"size-4 fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M5 13V3M2.5 5.5 5 3l2.5 2.5M11 3v10M8.5 10.5 11 13l2.5-2.5\" />\n </svg>\n <span class=\"text-sm font-semibold text-sui-ink\">{{ title }}</span>\n <button\n v-if=\"current\"\n class=\"ml-auto inline-flex h-7 items-center rounded-lg px-2 text-12.5 font-medium text-sui-ink-muted outline-hidden transition-colors duration-150 hover:bg-sui-sunken hover:text-sui-ink focus-visible:sui-ring-inset\"\n type=\"button\"\n @click=\"clear\"\n >\n {{ clearLabel }}\n </button>\n </div>\n <RadioGroupRoot\n :aria-label=\"title\"\n class=\"max-h-64 overflow-auto px-1.5 pt-1 pb-1.5\"\n :model-value=\"sort?.name\"\n @update:model-value=\"pickField($event as string)\"\n >\n <RadioGroupItem\n v-for=\"option in options\"\n :key=\"option.name\"\n :class=\"[\n row,\n option.name === sort?.name\n ? 'bg-sui-accent-wash font-semibold text-sui-accent'\n : 'text-sui-ink hover:bg-sui-sunken'\n ]\"\n :value=\"option.name\"\n >\n <span\n class=\"flex size-6 shrink-0 items-center justify-center rounded-md\"\n :class=\"\n option.name === sort?.name ? 'bg-sui-surface text-sui-accent' : 'bg-sui-sunken text-sui-ink-body'\n \"\n >\n <FilterGlyph :name=\"option.type\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ option.label }}</span>\n <CheckIcon v-if=\"option.name === sort?.name\" />\n </RadioGroupItem>\n </RadioGroupRoot>\n <RadioGroupRoot\n v-if=\"current\"\n :aria-label=\"directionLabel\"\n class=\"mx-3 mb-3 grid grid-cols-2 gap-0.5 rounded-lg bg-sui-sunken p-0.75\"\n :model-value=\"sort!.dir\"\n orientation=\"horizontal\"\n @update:model-value=\"sort = { name: sort!.name, dir: $event as ViewSort['dir'] }\"\n >\n <RadioGroupItem\n v-for=\"(dir, i) in ['asc', 'desc'] as const\"\n :key=\"dir\"\n class=\"flex h-9 items-center justify-center gap-1.5 rounded-md text-13 font-medium outline-hidden transition-colors duration-150 focus-visible:sui-ring-inset\"\n :class=\"\n sort!.dir === dir\n ? 'bg-sui-surface text-sui-ink shadow-(--sui-shadow-raised) ring-1 ring-sui-line-subtle'\n : 'text-sui-ink-body hover:text-sui-ink'\n \"\n :value=\"dir\"\n >\n <SortArrow :dir=\"dir\" />\n {{ words(current.type)[i] }}\n </RadioGroupItem>\n </RadioGroupRoot>\n </FilterFrame>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":";;;;;;;;;A,mNAgEM6B,IACJ,+K;;;;;;;;;;;;;;;;;;;;;;;;;;EAhCF,IAAMM,IAAQC,GAYRC,IAAOrC,EAA4BoC,GAAA,YAAkB,GACrDG,IAAOvC,EAAoBoC,GAAC,MAA0B,GAEtDI,IAAQC,EAAS,GAEjBC,IAAUC,QAAgBN,EAAK,QAAQF,EAAM,QAAQ,MAAM,MAAMS,EAAE,SAASP,EAAK,MAAO,IAAI,IAAI,KAAA,CAAU,GAC1GQ,KAAS,MAA0BV,EAAM,gBAAgBW,MAASC,EAAeD,IACjFE,IAAWL,QAAgBD,EAAQ,QAAQG,EAAMH,EAAQ,MAAM,IAAI,CAAC,CAAC,IAAK,MAAO,QAAQ,WAAkB,EAAG;EAEpH,SAASO,EAAU,GAAc;GAC/B,IAAMC,IAAQf,EAAM,QAAQ,MAAM,MAAMS,EAAE,SAASO,CAAI;GACvD,EAAK,QAAQ;IAAE;IAAM,KAAKd,EAAK,OAAO,SAASc,IAAOd,EAAK,MAAM,MAAOa,GAAO,WAAW;GAAO;EACnG;EAEA,SAASE,IAAQ;GAEf,AADA,EAAK,QAAQ,MACb,EAAK,QAAQ;EACf;E,iBAQqBhB,EAAA,OAAE,YAAiBM,EAAA,SAAtCzC,EAAA,GAAAC,EAsHcC,EAAAqD,CAAA,GAAA;;GAtHyC,MAAMjB,EAAA;GAAA,iBAAA,AAAAkB,EAAA,QAAA,MAAA,EAAI,QAAAC;;GAC/D,SAAAtD,QAciB,CAdKgC,EAAA,OAAE,YAAxBnC,EAAA,GAAAC,EAciBC,EAAAyD,CAAA,GAAA;;IAdsB,YAAA;;IACrC,SAAAxD,QAYS,CAZTC,EAYSC,GAZTC,EAAgBJ,EAYPqC,CAAA,GAZY;KAAG,UAAUJ,EAAA;KAAW,SAASM,EAAA,QAAO,WAAA;;KAC3D,SAAAtC,QASM,CATN,AAAAqD,EAAA,OAAAjD,EASM,OAAA;MARJ,eAAY;MACZ,OAAM;MACN,kBAAe;MACf,mBAAgB;MAChB,gBAAa;MACb,SAAQ;K,IAERA,EAAuE,QAAA,EAAjE,GAAE,6DAA4D,CAAA,C,QAChEC,EAAA,MACNC,EAAG0B,EAAA,WAAW,GAAA,CAAA,C;;;;G,OAGlBnC,EAAA,GAAAC,EAkBiBC,EAAAyD,CAAA,GAlBjBrD,EAkBiB,EAAA,KAAA,EAAA,GAhBPJ,EAAAqC,CAAA,GAAK,EACb,OAAM,4XAA2X,CAAA,GAAA;IAEjY,SAAApC,QAA8B;KAA9BC,EAA8BM,GAAA,EAAlB,KAAK0B,EAAA,MAAM,I;KACvB7B,EAEC,QAAA,MAAA,CADEA,EAAsD,QAAtDiB,GAAsDf,EAAzBgC,EAAA,MAAS,KAAK,IAAG,KAAC,CAAA,GAAUjC,EAAAC,EAAA,GAAG,IAAAA,EAAMsC,EAAA,KAAQ,GAAA,CAAA,C;KAE7E,AAAAS,EAAA,OAAAjD,EAQM,OAAA;MAPJ,eAAY;MACZ,OAAM;MACN,kBAAe;MACf,gBAAa;MACb,SAAQ;K,IAERA,EAAyB,QAAA,EAAnB,GAAE,eAAc,CAAA,C;;;G,SAG1BH,EAkFgBF,EAAA+D,CAAA,GAAA,MAAA;IAjFd,SAAA9D,QAgFiB,CAhFjBC,EAgFiBF,EAAAgE,CAAA,GAAA;KA/Ef,OAAM;KACN,OAAM;KACL,eAAa;;KAEd,SAAA/D,QA0Ec,CA1EdC,EA0EcO,GAAA;MA1EA,eAAawB,EAAA;MAAa,eAAaA,EAAA;MAAY,QAAQA,EAAA;MAAS,SAAK,AAAAqB,EAAA,QAAA,MAAE,EAAA,QAAI;;MAC3F,SAAArD,QAoBM;OApBNI,EAoBM,OApBNkB,GAoBM;QAnBJ,AAAA+B,EAAA,OAAAjD,EASM,OAAA;SARJ,eAAY;SACZ,OAAM;SACN,kBAAe;SACf,mBAAgB;SAChB,gBAAa;SACb,SAAQ;Q,IAERA,EAAuE,QAAA,EAAjE,GAAE,6DAA4D,CAAA,C;QAEtEA,EAAmE,QAAnEmB,GAAmEjB,EAAf0B,EAAA,KAAK,GAAA,CAAA;QAEjDM,EAAA,SADRzC,EAAA,GAAAY,EAOS,UAAA;;SALP,OAAM;SACN,MAAK;SACJ,SAAOuC;QAEL,GAAA1C,EAAA0B,EAAA,UAAU,GAAA,CAAA,K;;OAGjB/B,EA4BiBF,EAAAmE,CAAA,GAAA;QA3Bd,cAAYlC,EAAA;QACb,OAAM;QACL,eAAaC,EAAA,OAAM;QACnB,uBAAkB,AAAAoB,EAAA,QAAA,MAAER,EAAUS,CAAM;;QAGnC,SAAAtD,QAAyB,EAD3BH,EAAA,EAAA,GAAAY,EAqBiBE,GAAA,MAAAC,EApBEoB,EAAA,UAAV,OADTnC,EAAA,GAAAC,EAqBiBC,EAAAsE,CAAA,GAAA;SAnBd,KAAKC,EAAO;SACZ,OAAKzD,EAAA,CAAoBY,GAAqB6C,EAAO,SAASrC,EAAA,OAAM,O;SAMpE,OAAOqC,EAAO;;SAEf,SAAAtE,QAOO;UAPPI,EAOO,QAAA,EANL,OAAKS,EAAA,CAAC,+DACqByD,EAAO,SAASrC,EAAA,OAAM,OAAI,mCAAA,iC,OAIrDhC,EAAmCa,GAAA,EAArB,MAAMwD,EAAO,K;UAE7BlE,EAA+D,QAA/DoB,GAA+DlB,EAAtBgE,EAAO,KAAK,GAAA,CAAA;UACpCA,EAAO,SAASrC,EAAA,OAAM,QAAvCpC,EAAA,GAAAC,EAA+CiB,GAAA,EAAA,KAAA,EAAA,CAAA,K;;;;;;OAI3CuB,EAAA,SADRzC,EAAA,GAAAC,EAsBiBC,EAAAmE,CAAA,GAAA;;QApBd,cAAYlC,EAAA;QACb,OAAM;QACL,eAAaC,EAAA,MAAM;QACpB,aAAY;QACX,uBAAkB,AAAAoB,EAAA,QAAA,MAAE,EAAA,QAAI;SAAA,MAAWpB,EAAA,MAAM;SAAI,KAAOqB;QAAM;;QAGzD,SAAAtD,QAA4C,EAD9CH,EAAA,GAAAY,EAaiBE,GAAA,MAAAC,EAZI,CAAA,OAAA,MAAA,IAAX,GAAK,MADfX,EAaiBF,EAAAsE,CAAA,GAAA;SAXd,KAAKG;SACN,OAAK3D,EAAA,CAAC,0JACmBoB,EAAA,MAAM,QAAQuC,I;SAKtC,OAAOA;;SAER,SAAAxE,QAAwB,CAAxBC,EAAwBM,GAAA,EAAP,OAAG,GAAA,MAAA,GAAA,CAAA,KAAA,CAAA,GAAIF,EAAA,MACxBC,EAAGmC,EAAMH,EAAA,MAAQ,IAAI,CAAA,CAAEmC,EAAC,GAAA,CAAA,C"}
|
|
@@ -5,4 +5,4 @@ export type { FilterMenuProps } from './FilterMenu.vue';
|
|
|
5
5
|
export { default as SortMenu } from './SortMenu.vue';
|
|
6
6
|
export type { SortMenuProps } from './SortMenu.vue';
|
|
7
7
|
export { datePresets, describeFilter, filterOperators, sortDirections } from './defaults';
|
|
8
|
-
export type { FilterField, FilterFieldType, FilterOperator, FilterOption, FilterValue, ViewSort } from './types';
|
|
8
|
+
export type { FilterField, FilterFieldType, FilterOperator, FilterOption, FilterSummary, FilterValue, ViewSort } from './types';
|
|
@@ -5,6 +5,14 @@ export interface FilterField {
|
|
|
5
5
|
type: FilterFieldType;
|
|
6
6
|
/** A heading the picker lists the field under, e.g. "Activity". */
|
|
7
7
|
group?: string;
|
|
8
|
+
/** The direction SortMenu starts this field in; ascending by default. Newest first suits most dates. */
|
|
9
|
+
sortDir?: 'asc' | 'desc';
|
|
10
|
+
}
|
|
11
|
+
/** How a filter chip reads: the field, the operator and the value, each optional. */
|
|
12
|
+
export interface FilterSummary {
|
|
13
|
+
field?: string;
|
|
14
|
+
op?: string;
|
|
15
|
+
value?: string;
|
|
8
16
|
}
|
|
9
17
|
export interface FilterOperator {
|
|
10
18
|
value: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","names":["_sfc_main","Popover_vue_vue_type_script_setup_true_lang_default","Popover_default"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-lg border border-sui-line-subtle bg-sui-surface text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n side=\"bottom\"\n :side-offset=\"offset\"\n :style=\"{ width }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"onEscape\"\n @focus-outside.prevent\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <slot :hide=\"hide\" />\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Popover.js","names":["_sfc_main","Popover_vue_vue_type_script_setup_true_lang_default","Popover_default"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-lg outline-hidden border border-sui-line-subtle bg-sui-surface text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n side=\"bottom\"\n :side-offset=\"offset\"\n :style=\"{ width }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"onEscape\"\n @focus-outside.prevent\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <slot :hide=\"hide\" />\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
|
|
@@ -65,7 +65,7 @@ var _ = /*@__PURE__*/ n({
|
|
|
65
65
|
align: "start",
|
|
66
66
|
"align-offset": n.alignOffset,
|
|
67
67
|
"aria-label": T.value,
|
|
68
|
-
class: "z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-lg border border-sui-line-subtle bg-sui-surface text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in",
|
|
68
|
+
class: "z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-lg outline-hidden border border-sui-line-subtle bg-sui-surface text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in",
|
|
69
69
|
"collision-padding": 8,
|
|
70
70
|
side: "bottom",
|
|
71
71
|
"side-offset": n.offset,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_withCtx","_createVNode","_mergeProps","_withModifiers","_renderSlot","Popover_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","attrs","useAttrs","open","ref","anchor","opener","label","pressedOutside","show","event","target","hide","toggle","isOnAnchor","el","onPointerDownOutside","onEscape","onCloseAutoFocus","active","onOpenAutoFocus","panel","onScroll","watch","isOpen","onBeforeUnmount","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","PopoverPortal","PopoverContent","mergeProps","_ctx","withModifiers","renderSlot"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-lg border border-sui-line-subtle bg-sui-surface text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n side=\"bottom\"\n :side-offset=\"offset\"\n :style=\"{ width }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"onEscape\"\n @focus-outside.prevent\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <slot :hide=\"hide\" />\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Popover.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_withCtx","_createVNode","_mergeProps","_withModifiers","_renderSlot","Popover_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","attrs","useAttrs","open","ref","anchor","opener","label","pressedOutside","show","event","target","hide","toggle","isOnAnchor","el","onPointerDownOutside","onEscape","onCloseAutoFocus","active","onOpenAutoFocus","panel","onScroll","watch","isOpen","onBeforeUnmount","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","PopoverPortal","PopoverContent","mergeProps","_ctx","withModifiers","renderSlot"],"sources":["../../../src/components/Popover/Popover.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, useAttrs, watch } from 'vue'\n\nimport { PopoverAnchor, PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\n\nexport interface PopoverProps {\n /** The gap to the anchor, in px; negative overlaps it. */\n offset?: number\n /** Shifts it along the anchor's edge, in px. */\n alignOffset?: number\n closeOnEscape?: boolean\n /** The panel's width, e.g. `20rem`. */\n width?: string\n}\n\n// Root is Reka's renderless PopoverRoot: class and attributes belong on the panel.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<PopoverProps>(), {\n offset: 4,\n alignOffset: 0,\n closeOnEscape: true,\n width: '16rem'\n})\n\nconst emit = defineEmits<{ show: []; hide: [] }>()\n\nconst attrs = useAttrs()\n\nconst open = ref(false)\nconst anchor = ref<HTMLElement>()\n// What was clicked to open it; clicks on it toggle the popover rather than counting as outside.\nconst opener = ref<HTMLElement>()\nconst label = ref<string>()\n// A press outside closes it and leaves focus to what was pressed.\nlet pressedOutside = false\n\n/** Opens below the event's element, or below `target` when given. */\nfunction show(event: Event, target?: HTMLElement) {\n opener.value = event.currentTarget as HTMLElement\n anchor.value = target ?? opener.value\n // A dialog needs a name: an aria-label given to the popover, or else the name of the element it opened from.\n label.value =\n (attrs['aria-label'] as string | undefined) ??\n opener.value?.getAttribute('aria-label') ??\n opener.value?.textContent?.trim()\n pressedOutside = false\n open.value = true\n}\n\nfunction hide() {\n open.value = false\n}\n\nfunction toggle(event: Event, target?: HTMLElement) {\n if (open.value) hide()\n else show(event, target)\n}\n\ndefineExpose({ show, hide, toggle })\n\nfunction isOnAnchor(target: EventTarget | null) {\n return target instanceof Node && [anchor.value, opener.value].some((el) => el?.contains(target))\n}\n\nfunction onPointerDownOutside(event: CustomEvent<{ originalEvent: PointerEvent }>) {\n if (isOnAnchor(event.detail.originalEvent.target)) event.preventDefault()\n else pressedOutside = true\n}\n\nfunction onEscape(event: KeyboardEvent) {\n if (!props.closeOnEscape) event.preventDefault()\n}\n\n// Otherwise focus left in the panel goes back to the anchor.\nfunction onCloseAutoFocus(event: Event) {\n event.preventDefault()\n const active = document.activeElement\n const inPanel = !active || active === document.body || (event.target as HTMLElement).contains(active)\n if (inPanel && !pressedOutside) anchor.value?.focus()\n}\n\n// Focus goes to an [autofocus] element inside, or else the panel, so Tab moves through it and Escape works at once.\n// The event comes from Reka's positioning wrapper around the panel.\nfunction onOpenAutoFocus(event: Event) {\n event.preventDefault()\n const wrapper = event.target as HTMLElement | null\n const panel = wrapper?.querySelector<HTMLElement>('[role=\"dialog\"]')\n ;(panel?.querySelector<HTMLElement>('[autofocus]') ?? panel)?.focus()\n}\n\n// It closes when the page moves under it: a scrolling ancestor of the anchor, or a resized window.\nfunction onScroll(event: Event) {\n if (event.target instanceof Node && event.target.contains(anchor.value ?? null)) hide()\n}\n\nwatch(open, (isOpen) => {\n if (isOpen) {\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', hide)\n emit('show')\n } else {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n emit('hide')\n }\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', hide)\n})\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor :reference=\"anchor\" />\n <PopoverPortal>\n <PopoverContent\n v-bind=\"$attrs\"\n align=\"start\"\n :align-offset=\"alignOffset\"\n :aria-label=\"label\"\n class=\"z-[1100] block max-h-(--reka-popover-content-available-height) origin-center overflow-y-auto rounded-lg outline-hidden border border-sui-line-subtle bg-sui-surface text-sui-ink shadow-xl data-[state=closed]:animate-sui-overlay-out data-[state=open]:animate-sui-overlay-in\"\n :collision-padding=\"8\"\n side=\"bottom\"\n :side-offset=\"offset\"\n :style=\"{ width }\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @escape-key-down=\"onEscape\"\n @focus-outside.prevent\n @open-auto-focus=\"onOpenAutoFocus\"\n @pointer-down-outside=\"onPointerDownOutside\"\n >\n <slot :hide=\"hide\" />\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Table.js","names":["_sfc_main","Table_vue_vue_type_script_setup_true_lang_default","Table_default"],"sources":["../../../src/components/Table/Table.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends Record<string, any>\">\nimport { computed } from 'vue'\n\nimport Checkbox from '../Checkbox/Checkbox.vue'\nimport Skeleton from '../Skeleton/Skeleton.vue'\nimport type { TableColumn, TableSort } from './types'\n\nexport interface TableProps<T> {\n columns: TableColumn[]\n rows: T[]\n /** The row field that identifies it. */\n rowKey?: keyof T & string\n /** A checkbox column bound to `v-model:selected`; selected rows tint accent-wash. */\n selectable?: boolean\n /** Skeleton rows in place of the body. */\n loading?: boolean\n loadingRows?: number\n /** md: 57px rows. sm: 40px, for dense lists. */\n size?: 'md' | 'sm'\n /** The table's name for screen readers. */\n caption?: string\n selectAllLabel?: string\n selectRowLabel?: string\n /** Makes rows clickable (`@row-click`), e.g. to open the record. */\n onRowClick?: (row: T) => void\n}\n\nconst props = withDefaults(defineProps<TableProps<T>>(), {\n rowKey: 'id' as never,\n loadingRows: 5,\n size: 'md',\n caption: undefined,\n selectAllLabel: 'Select all rows',\n selectRowLabel: 'Select row',\n onRowClick: undefined\n})\n\nconst sort = defineModel<TableSort | null>('sort', { default: null })\nconst selected = defineModel<unknown[]>('selected', { default: () => [] })\n\nconst slots = defineSlots<\n {\n /** Shown in place of the body when there are no rows, e.g. an EmptyState. */\n empty?: () => unknown\n /** Replaces the body when given, e.g. an inset danger Alert with a retry. */\n error?: () => unknown\n /** A canvas strip under the rows: a rows-per-page Select, the range, Pagination. */\n footer?: () => unknown\n } & {\n [K in `cell-${string}`]?: (props: { row: T; value: unknown }) => unknown\n }\n>()\n\nconst idOf = (row: T): unknown => row[props.rowKey ?? 'id']\nconst ids = computed(() => props.rows.map(idOf))\nconst allSelected = computed(() => ids.value.length > 0 && ids.value.every((id) => selected.value.includes(id)))\nconst someSelected = computed(() => !allSelected.value && ids.value.some((id) => selected.value.includes(id)))\n\nfunction toggleAll() {\n selected.value = allSelected.value\n ? selected.value.filter((id) => !ids.value.includes(id))\n : [...new Set([...selected.value, ...ids.value])]\n}\n\nfunction toggle(id: unknown) {\n selected.value = selected.value.includes(id) ? selected.value.filter((x) => x !== id) : [...selected.value, id]\n}\n\n// Sorting a column cycles ascending, descending, unsorted.\nfunction sortBy(key: string) {\n const dir = sort.value?.key === key ? sort.value.dir : null\n const next = dir === null ? 'asc' : dir === 'asc' ? 'desc' : null\n sort.value = next ? { key, dir: next } : null\n}\n\nfunction dirOf(key: string) {\n return sort.value?.key === key ? sort.value.dir : null\n}\n\nfunction ariaSort(column: TableColumn) {\n const dir = dirOf(column.key)\n if (dir) return dir === 'asc' ? 'ascending' : 'descending'\n return column.sortable ? 'none' : undefined\n}\n\nconst state = computed(() => {\n if (slots.error) return 'error'\n if (props.loading) return 'loading'\n return props.rows.length === 0 && slots.empty ? 'empty' : 'rows'\n})\n\nconst columnCount = computed(() => props.columns.length + (props.selectable ? 1 : 0))\nconst alignClass = { left: 'text-left', center: 'text-center', right: 'text-right' }\nconst skeletonWidths = ['60%', '45%', '70%', '35%', '55%']\n\nconst sm = computed(() => props.size === 'sm')\nconst th = computed(() => [\n 'border-b border-sui-line-subtle text-13 font-medium whitespace-nowrap',\n sm.value ? 'h-9' : 'h-11'\n])\nconst td = computed(() => [\n '
|
|
1
|
+
{"version":3,"file":"Table.js","names":["_sfc_main","Table_vue_vue_type_script_setup_true_lang_default","Table_default"],"sources":["../../../src/components/Table/Table.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends Record<string, any>\">\nimport { computed } from 'vue'\n\nimport Checkbox from '../Checkbox/Checkbox.vue'\nimport Skeleton from '../Skeleton/Skeleton.vue'\nimport type { TableColumn, TableSort } from './types'\n\nexport interface TableProps<T> {\n columns: TableColumn[]\n rows: T[]\n /** The row field that identifies it. */\n rowKey?: keyof T & string\n /** A checkbox column bound to `v-model:selected`; selected rows tint accent-wash. */\n selectable?: boolean\n /** Skeleton rows in place of the body. */\n loading?: boolean\n loadingRows?: number\n /** md: 57px rows. sm: 40px, for dense lists. */\n size?: 'md' | 'sm'\n /** The table's name for screen readers. */\n caption?: string\n selectAllLabel?: string\n selectRowLabel?: string\n /** Makes rows clickable (`@row-click`), e.g. to open the record. */\n onRowClick?: (row: T) => void\n}\n\nconst props = withDefaults(defineProps<TableProps<T>>(), {\n rowKey: 'id' as never,\n loadingRows: 5,\n size: 'md',\n caption: undefined,\n selectAllLabel: 'Select all rows',\n selectRowLabel: 'Select row',\n onRowClick: undefined\n})\n\nconst sort = defineModel<TableSort | null>('sort', { default: null })\nconst selected = defineModel<unknown[]>('selected', { default: () => [] })\n\nconst slots = defineSlots<\n {\n /** Shown in place of the body when there are no rows, e.g. an EmptyState. */\n empty?: () => unknown\n /** Replaces the body when given, e.g. an inset danger Alert with a retry. */\n error?: () => unknown\n /** A canvas strip under the rows: a rows-per-page Select, the range, Pagination. */\n footer?: () => unknown\n } & {\n [K in `cell-${string}`]?: (props: { row: T; value: unknown }) => unknown\n }\n>()\n\nconst idOf = (row: T): unknown => row[props.rowKey ?? 'id']\nconst ids = computed(() => props.rows.map(idOf))\nconst allSelected = computed(() => ids.value.length > 0 && ids.value.every((id) => selected.value.includes(id)))\nconst someSelected = computed(() => !allSelected.value && ids.value.some((id) => selected.value.includes(id)))\n\nfunction toggleAll() {\n selected.value = allSelected.value\n ? selected.value.filter((id) => !ids.value.includes(id))\n : [...new Set([...selected.value, ...ids.value])]\n}\n\nfunction toggle(id: unknown) {\n selected.value = selected.value.includes(id) ? selected.value.filter((x) => x !== id) : [...selected.value, id]\n}\n\n// Sorting a column cycles ascending, descending, unsorted.\nfunction sortBy(key: string) {\n const dir = sort.value?.key === key ? sort.value.dir : null\n const next = dir === null ? 'asc' : dir === 'asc' ? 'desc' : null\n sort.value = next ? { key, dir: next } : null\n}\n\nfunction dirOf(key: string) {\n return sort.value?.key === key ? sort.value.dir : null\n}\n\nfunction ariaSort(column: TableColumn) {\n const dir = dirOf(column.key)\n if (dir) return dir === 'asc' ? 'ascending' : 'descending'\n return column.sortable ? 'none' : undefined\n}\n\nconst state = computed(() => {\n if (slots.error) return 'error'\n if (props.loading) return 'loading'\n return props.rows.length === 0 && slots.empty ? 'empty' : 'rows'\n})\n\nconst columnCount = computed(() => props.columns.length + (props.selectable ? 1 : 0))\nconst alignClass = { left: 'text-left', center: 'text-center', right: 'text-right' }\nconst skeletonWidths = ['60%', '45%', '70%', '35%', '55%']\n\nconst sm = computed(() => props.size === 'sm')\nconst th = computed(() => [\n 'border-b border-sui-line-subtle text-13 font-medium whitespace-nowrap',\n sm.value ? 'h-9' : 'h-11'\n])\nconst td = computed(() => [\n 'border-b border-sui-line-subtle align-middle text-sui-ink-body group-last/row:border-b-0',\n sm.value ? 'h-10' : 'h-[3.5625rem]'\n])\nconst pad = computed(() => (sm.value ? 'px-3 py-1.5' : 'px-4 py-3'))\nconst headPad = computed(() => (sm.value ? 'px-3' : 'px-4'))\nconst checkCell = 'w-12 pl-4'\n</script>\n\n<!-- A data table: sunken header strip, sortable headers, selection, loading, empty and error states, a footer. -->\n<template>\n <div class=\"overflow-hidden rounded-xl border border-sui-line-subtle bg-sui-surface text-sm text-sui-ink\">\n <div class=\"overflow-x-auto\">\n <table class=\"w-full min-w-[var(--sui-table-min,720px)] table-fixed border-collapse\">\n <caption v-if=\"caption\" class=\"sr-only\">\n {{\n caption\n }}\n </caption>\n <colgroup>\n <col v-if=\"selectable\" class=\"w-12\" />\n <col\n v-for=\"column in columns\"\n :key=\"column.key\"\n :style=\"{ width: typeof column.width === 'number' ? `${column.width}px` : column.width }\"\n />\n </colgroup>\n <thead>\n <tr>\n <th v-if=\"selectable\" class=\"bg-sui-sunken\" :class=\"[th, checkCell]\">\n <Checkbox\n :aria-label=\"selectAllLabel\"\n :disabled=\"loading || rows.length === 0\"\n :indeterminate=\"someSelected\"\n :model-value=\"allSelected\"\n @update:model-value=\"toggleAll\"\n />\n </th>\n <component\n :is=\"column.label ? 'th' : 'td'\"\n v-for=\"column in columns\"\n :key=\"column.key\"\n :aria-sort=\"ariaSort(column)\"\n :class=\"[\n th,\n headPad,\n alignClass[column.align ?? 'left'],\n dirOf(column.key) ? 'bg-sui-accent-wash text-sui-accent' : 'bg-sui-sunken text-sui-ink-subtle'\n ]\"\n :scope=\"column.label ? 'col' : undefined\"\n >\n <button\n v-if=\"column.sortable\"\n class=\"inline-flex h-full w-full items-center gap-1.5 rounded-md outline-hidden focus-visible:sui-ring-inset\"\n :class=\"[\n column.align === 'right' && 'justify-end',\n column.align === 'center' && 'justify-center',\n !dirOf(column.key) && 'hover:text-sui-ink'\n ]\"\n type=\"button\"\n @click=\"sortBy(column.key)\"\n >\n {{ column.label }}\n <svg\n aria-hidden=\"true\"\n class=\"size-3 shrink-0 fill-none stroke-current\"\n :class=\"!dirOf(column.key) && 'opacity-50'\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.5\"\n viewBox=\"0 0 12 12\"\n >\n <path v-if=\"dirOf(column.key) === 'asc'\" d=\"M3 7.5 6 4.5l3 3\" />\n <path v-else-if=\"dirOf(column.key) === 'desc'\" d=\"M3 4.5 6 7.5l3-3\" />\n <path v-else d=\"M3.5 4.5 6 2l2.5 2.5M3.5 7.5 6 10l2.5-2.5\" />\n </svg>\n </button>\n <template v-else>{{ column.label }}</template>\n </component>\n </tr>\n </thead>\n <tbody :aria-busy=\"loading || undefined\">\n <tr v-if=\"state === 'error' || state === 'empty'\">\n <td class=\"p-0\" :colspan=\"columnCount\">\n <slot :name=\"state\" />\n </td>\n </tr>\n <template v-else-if=\"state === 'loading'\">\n <tr v-for=\"i in loadingRows\" :key=\"i\" aria-hidden=\"true\" class=\"group/row\">\n <td v-if=\"selectable\" :class=\"[td, checkCell]\"><Skeleton size=\"1rem\" /></td>\n <td v-for=\"(column, j) in columns\" :key=\"column.key\" :class=\"[td, pad]\">\n <Skeleton height=\"0.75rem\" :width=\"skeletonWidths[(i + j) % 5]\" />\n </td>\n </tr>\n </template>\n <template v-else>\n <tr\n v-for=\"row in rows\"\n :key=\"idOf(row) as PropertyKey\"\n :aria-selected=\"selectable ? selected.includes(idOf(row)) : undefined\"\n class=\"group/row transition-colors duration-150\"\n :class=\"[\n selected.includes(idOf(row)) ? 'bg-sui-accent-wash' : 'hover:bg-sui-sunken',\n onRowClick && 'cursor-pointer'\n ]\"\n @click=\"onRowClick?.(row)\"\n >\n <td v-if=\"selectable\" :class=\"[td, checkCell]\" @click.stop>\n <Checkbox\n :aria-label=\"selectRowLabel\"\n :model-value=\"selected.includes(idOf(row))\"\n @update:model-value=\"toggle(idOf(row))\"\n />\n </td>\n <td\n v-for=\"column in columns\"\n :key=\"column.key\"\n :class=\"[\n td,\n pad,\n alignClass[column.align ?? 'left'],\n column.wrap ? 'break-words whitespace-normal' : 'truncate'\n ]\"\n >\n <slot :name=\"`cell-${column.key}`\" :row=\"row\" :value=\"row[column.key]\">\n <template v-if=\"row[column.key] != null && row[column.key] !== ''\">{{ row[column.key] }}</template>\n <span v-else class=\"text-sui-ink-muted\">–</span>\n </slot>\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n </div>\n <div\n v-if=\"$slots.footer\"\n class=\"flex flex-wrap items-center justify-between gap-3 border-t border-sui-line-subtle bg-sui-canvas py-2 pr-3 pl-4 text-13 text-sui-ink-muted\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -79,7 +79,7 @@ var C = { class: "overflow-hidden rounded-xl border border-sui-line-subtle bg-su
|
|
|
79
79
|
"70%",
|
|
80
80
|
"35%",
|
|
81
81
|
"55%"
|
|
82
|
-
], X = r(() => d.size === "sm"), Z = r(() => ["border-b border-sui-line-subtle text-13 font-medium whitespace-nowrap", X.value ? "h-9" : "h-11"]), Q = r(() => ["
|
|
82
|
+
], X = r(() => d.size === "sm"), Z = r(() => ["border-b border-sui-line-subtle text-13 font-medium whitespace-nowrap", X.value ? "h-9" : "h-11"]), Q = r(() => ["border-b border-sui-line-subtle align-middle text-sui-ink-body group-last/row:border-b-0", X.value ? "h-10" : "h-[3.5625rem]"]), $ = r(() => X.value ? "px-3 py-1.5" : "px-4 py-3"), ae = r(() => X.value ? "px-3" : "px-4");
|
|
83
83
|
return (r, d) => (m(), o("div", C, [s("div", w, [s("table", T, [
|
|
84
84
|
u.caption ? (m(), o("caption", E, v(u.caption), 1)) : a("", !0),
|
|
85
85
|
s("colgroup", null, [u.selectable ? (m(), o("col", D)) : a("", !0), (m(!0), o(n, null, h(u.columns, (e) => (m(), o("col", {
|
|
@@ -172,7 +172,8 @@ var C = { class: "overflow-hidden rounded-xl border border-sui-line-subtle bg-su
|
|
|
172
172
|
class: f([
|
|
173
173
|
Q.value,
|
|
174
174
|
$.value,
|
|
175
|
-
J[t.align ?? "left"]
|
|
175
|
+
J[t.align ?? "left"],
|
|
176
|
+
t.wrap ? "break-words whitespace-normal" : "truncate"
|
|
176
177
|
])
|
|
177
178
|
}, [g(r.$slots, `cell-${t.key}`, {
|
|
178
179
|
row: e,
|