@dou-ui/dashboard 0.0.0-stage → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/chart/chart-settings.js +6 -0
- package/dist/chart/chart-settings.js.map +1 -0
- package/dist/chart/chart-settings.vue_vue_type_script_setup_true_lang.js +122 -0
- package/dist/chart/chart-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/chart/chart.js +6 -0
- package/dist/chart/chart.js.map +1 -0
- package/dist/chart/chart.vue_vue_type_script_setup_true_lang.js +99 -0
- package/dist/chart/chart.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/chart/index.js +33 -0
- package/dist/chart/index.js.map +1 -0
- package/dist/collaboration/index.js +281 -0
- package/dist/collaboration/index.js.map +1 -0
- package/dist/collaboration/order.js +88 -0
- package/dist/collaboration/order.js.map +1 -0
- package/dist/core/document.js +128 -0
- package/dist/core/document.js.map +1 -0
- package/dist/core/history.js +66 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/transaction.js +218 -0
- package/dist/core/transaction.js.map +1 -0
- package/dist/dashboard/dashboard.js +6 -0
- package/dist/dashboard/dashboard.js.map +1 -0
- package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js +1072 -0
- package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/dashboard/export.js +77 -0
- package/dist/dashboard/export.js.map +1 -0
- package/dist/dashboard/filter-bar.js +6 -0
- package/dist/dashboard/filter-bar.js.map +1 -0
- package/dist/dashboard/filter-bar.vue_vue_type_script_setup_true_lang.js +150 -0
- package/dist/dashboard/filter-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/dashboard/frame-context.js +5 -0
- package/dist/dashboard/frame-context.js.map +1 -0
- package/dist/dashboard/observers.js +48 -0
- package/dist/dashboard/observers.js.map +1 -0
- package/dist/dashboard/palette.js +6 -0
- package/dist/dashboard/palette.js.map +1 -0
- package/dist/dashboard/palette.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/dashboard/palette.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/dashboard/widget-body.js +6 -0
- package/dist/dashboard/widget-body.js.map +1 -0
- package/dist/dashboard/widget-body.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/dashboard/widget-body.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/dashboard/widget-frame.js +6 -0
- package/dist/dashboard/widget-frame.js.map +1 -0
- package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js +300 -0
- package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/dashboard/widget-settings.js +6 -0
- package/dist/dashboard/widget-settings.js.map +1 -0
- package/dist/dashboard/widget-settings.vue_vue_type_script_setup_true_lang.js +36 -0
- package/dist/dashboard/widget-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/data/context.js +5 -0
- package/dist/data/context.js.map +1 -0
- package/dist/data/filters.js +31 -0
- package/dist/data/filters.js.map +1 -0
- package/dist/data/store.js +214 -0
- package/dist/data/store.js.map +1 -0
- package/dist/grid/grid-handle.js +6 -0
- package/dist/grid/grid-handle.js.map +1 -0
- package/dist/grid/grid-handle.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/grid/grid-handle.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/grid/grid-item.js +80 -0
- package/dist/grid/grid-item.js.map +1 -0
- package/dist/grid/grid-layout.js +6 -0
- package/dist/grid/grid-layout.js.map +1 -0
- package/dist/grid/grid-layout.vue_vue_type_script_setup_true_lang.js +767 -0
- package/dist/grid/grid-layout.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/grid/tiers.js +31 -0
- package/dist/grid/tiers.js.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/engine.js +284 -0
- package/dist/layout/engine.js.map +1 -0
- package/dist/layout/index.js +1 -0
- package/dist/locale.js +245 -0
- package/dist/locale.js.map +1 -0
- package/dist/pivot/index.js +47 -0
- package/dist/pivot/index.js.map +1 -0
- package/dist/pivot/pivot-settings.js +6 -0
- package/dist/pivot/pivot-settings.js.map +1 -0
- package/dist/pivot/pivot-settings.vue_vue_type_script_setup_true_lang.js +64 -0
- package/dist/pivot/pivot-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/pivot/pivot.js +6 -0
- package/dist/pivot/pivot.js.map +1 -0
- package/dist/pivot/pivot.vue_vue_type_script_setup_true_lang.js +76 -0
- package/dist/pivot/pivot.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/style.d.ts +1 -0
- package/dist/style.js +12 -0
- package/dist/types/chart/chart-settings.vue.d.ts +11 -0
- package/dist/types/chart/chart.vue.d.ts +3 -0
- package/dist/types/chart/index.d.ts +9 -0
- package/dist/types/chart/types.d.ts +23 -0
- package/dist/types/collaboration/index.d.ts +53 -0
- package/dist/types/collaboration/order.d.ts +20 -0
- package/dist/types/core/collaboration.d.ts +51 -0
- package/dist/types/core/document.d.ts +35 -0
- package/dist/types/core/history.d.ts +15 -0
- package/dist/types/core/transaction.d.ts +86 -0
- package/dist/types/core/types.d.ts +27 -0
- package/dist/types/dashboard/dashboard.vue.d.ts +33 -0
- package/dist/types/dashboard/export.d.ts +11 -0
- package/dist/types/dashboard/filter-bar.vue.d.ts +19 -0
- package/dist/types/dashboard/frame-context.d.ts +54 -0
- package/dist/types/dashboard/observers.d.ts +15 -0
- package/dist/types/dashboard/palette.vue.d.ts +20 -0
- package/dist/types/dashboard/types.d.ts +190 -0
- package/dist/types/dashboard/widget-body.vue.d.ts +19 -0
- package/dist/types/dashboard/widget-frame.vue.d.ts +6 -0
- package/dist/types/dashboard/widget-settings.vue.d.ts +16 -0
- package/dist/types/data/context.d.ts +18 -0
- package/dist/types/data/filters.d.ts +9 -0
- package/dist/types/data/store.d.ts +48 -0
- package/dist/types/data/types.d.ts +67 -0
- package/dist/types/grid/grid-handle.vue.d.ts +18 -0
- package/dist/types/grid/grid-item.d.ts +78 -0
- package/dist/types/grid/grid-layout.vue.d.ts +46 -0
- package/dist/types/grid/tiers.d.ts +12 -0
- package/dist/types/grid/types.d.ts +113 -0
- package/dist/types/index.d.ts +295 -0
- package/dist/types/layout/engine.d.ts +50 -0
- package/dist/types/layout/index.d.ts +2 -0
- package/dist/types/layout/types.d.ts +39 -0
- package/dist/types/locale.d.ts +117 -0
- package/dist/types/pivot/index.d.ts +14 -0
- package/dist/types/pivot/pivot-settings.vue.d.ts +16 -0
- package/dist/types/pivot/pivot.vue.d.ts +7 -0
- package/dist/types/pivot/types.d.ts +11 -0
- package/dist/types/widget/context.d.ts +91 -0
- package/dist/types/widget/define.d.ts +50 -0
- package/dist/types/widgets/field-select.vue.d.ts +18 -0
- package/dist/types/widgets/index.d.ts +15 -0
- package/dist/types/widgets/settings-field.vue.d.ts +17 -0
- package/dist/types/widgets/shared.d.ts +20 -0
- package/dist/types/widgets/source-field.vue.d.ts +15 -0
- package/dist/types/widgets/stat-settings.vue.d.ts +11 -0
- package/dist/types/widgets/stat.vue.d.ts +3 -0
- package/dist/types/widgets/table-settings.vue.d.ts +11 -0
- package/dist/types/widgets/table.vue.d.ts +3 -0
- package/dist/types/widgets/text-settings.vue.d.ts +11 -0
- package/dist/types/widgets/text.vue.d.ts +3 -0
- package/dist/types/widgets/types.d.ts +38 -0
- package/dist/widget/context.js +88 -0
- package/dist/widget/context.js.map +1 -0
- package/dist/widget/define.js +32 -0
- package/dist/widget/define.js.map +1 -0
- package/dist/widgets/field-select.js +6 -0
- package/dist/widgets/field-select.js.map +1 -0
- package/dist/widgets/field-select.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/widgets/field-select.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/index.js +74 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/settings-field.js +6 -0
- package/dist/widgets/settings-field.js.map +1 -0
- package/dist/widgets/settings-field.vue_vue_type_script_setup_true_lang.js +28 -0
- package/dist/widgets/settings-field.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/shared.js +68 -0
- package/dist/widgets/shared.js.map +1 -0
- package/dist/widgets/source-field.js +6 -0
- package/dist/widgets/source-field.js.map +1 -0
- package/dist/widgets/source-field.vue_vue_type_script_setup_true_lang.js +47 -0
- package/dist/widgets/source-field.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/stat-settings.js +6 -0
- package/dist/widgets/stat-settings.js.map +1 -0
- package/dist/widgets/stat-settings.vue_vue_type_script_setup_true_lang.js +107 -0
- package/dist/widgets/stat-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/stat.js +6 -0
- package/dist/widgets/stat.js.map +1 -0
- package/dist/widgets/stat.vue_vue_type_script_setup_true_lang.js +72 -0
- package/dist/widgets/stat.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/table-settings.js +6 -0
- package/dist/widgets/table-settings.js.map +1 -0
- package/dist/widgets/table-settings.vue_vue_type_script_setup_true_lang.js +90 -0
- package/dist/widgets/table-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/table.js +6 -0
- package/dist/widgets/table.js.map +1 -0
- package/dist/widgets/table.vue_vue_type_script_setup_true_lang.js +91 -0
- package/dist/widgets/table.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/text-settings.js +6 -0
- package/dist/widgets/text-settings.js.map +1 -0
- package/dist/widgets/text-settings.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/widgets/text-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/widgets/text.js +6 -0
- package/dist/widgets/text.js.map +1 -0
- package/dist/widgets/text.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/widgets/text.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/package.json +98 -4
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { format } from "../locale.js";
|
|
2
|
+
import { observersKey } from "./observers.js";
|
|
3
|
+
import { provideWidgetContext } from "../widget/context.js";
|
|
4
|
+
import { DouButton, DouEmpty, DouSpinner } from "dou-ui";
|
|
5
|
+
import { createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, onBeforeUnmount, onMounted, openBlock, ref, resolveDynamicComponent, toDisplayString, unref, withCtx } from "vue";
|
|
6
|
+
import { AlertCircleIcon } from "@dou-ui/icons";
|
|
7
|
+
// src/dashboard/widget-body.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
+
var _hoisted_1 = ["aria-busy"];
|
|
9
|
+
var _hoisted_2 = {
|
|
10
|
+
key: 1,
|
|
11
|
+
class: "dou-dashboard__notice"
|
|
12
|
+
};
|
|
13
|
+
var _hoisted_3 = {
|
|
14
|
+
key: 0,
|
|
15
|
+
class: "dou-dashboard__status is-loading",
|
|
16
|
+
role: "status"
|
|
17
|
+
};
|
|
18
|
+
var _hoisted_4 = {
|
|
19
|
+
key: 1,
|
|
20
|
+
class: "dou-dashboard__status is-error",
|
|
21
|
+
role: "alert"
|
|
22
|
+
};
|
|
23
|
+
var _hoisted_5 = {
|
|
24
|
+
key: 2,
|
|
25
|
+
class: "dou-dashboard__status is-empty"
|
|
26
|
+
};
|
|
27
|
+
var widget_body_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
28
|
+
name: "DouDashboardWidgetBody",
|
|
29
|
+
__name: "widget-body",
|
|
30
|
+
props: {
|
|
31
|
+
widget: {},
|
|
32
|
+
type: {},
|
|
33
|
+
editing: { type: Boolean },
|
|
34
|
+
fullscreen: { type: Boolean },
|
|
35
|
+
messages: {},
|
|
36
|
+
setProps: { type: Function },
|
|
37
|
+
setWorkbook: { type: Function }
|
|
38
|
+
},
|
|
39
|
+
setup(__props) {
|
|
40
|
+
const props = __props;
|
|
41
|
+
const body = ref();
|
|
42
|
+
const width = ref(0);
|
|
43
|
+
const height = ref(0);
|
|
44
|
+
const observers = inject(observersKey);
|
|
45
|
+
let stop;
|
|
46
|
+
onMounted(() => {
|
|
47
|
+
stop = observers?.size(body.value, (entry) => {
|
|
48
|
+
width.value = entry.contentRect.width;
|
|
49
|
+
height.value = entry.contentRect.height;
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
onBeforeUnmount(() => stop?.());
|
|
53
|
+
const { status } = provideWidgetContext({
|
|
54
|
+
widget: () => props.widget,
|
|
55
|
+
editing: () => props.editing,
|
|
56
|
+
fullscreen: () => !!props.fullscreen,
|
|
57
|
+
size: {
|
|
58
|
+
width,
|
|
59
|
+
height
|
|
60
|
+
},
|
|
61
|
+
setProps: props.setProps,
|
|
62
|
+
setWorkbook: props.setWorkbook
|
|
63
|
+
});
|
|
64
|
+
return (_ctx, _cache) => {
|
|
65
|
+
return openBlock(), createElementBlock("div", {
|
|
66
|
+
class: "dou-dashboard__body",
|
|
67
|
+
"aria-busy": unref(status).state === "loading" || void 0
|
|
68
|
+
}, [createElementVNode("div", {
|
|
69
|
+
ref_key: "body",
|
|
70
|
+
ref: body,
|
|
71
|
+
class: "dou-dashboard__content"
|
|
72
|
+
}, [__props.type ? (openBlock(), createBlock(resolveDynamicComponent(__props.type.component), { key: 0 })) : (openBlock(), createElementBlock("div", _hoisted_2, toDisplayString(unref(format)(__props.messages.unknownType, { type: __props.widget.type })), 1))], 512), unref(status).state === "loading" ? (openBlock(), createElementBlock("div", _hoisted_3, [createVNode(unref(DouSpinner), {
|
|
73
|
+
size: "sm",
|
|
74
|
+
label: __props.messages.loading
|
|
75
|
+
}, null, 8, ["label"])])) : unref(status).state === "error" ? (openBlock(), createElementBlock("div", _hoisted_4, [
|
|
76
|
+
createVNode(unref(AlertCircleIcon), { class: "dou-dashboard__status-icon" }),
|
|
77
|
+
createElementVNode("span", null, toDisplayString(unref(status).message || __props.messages.error), 1),
|
|
78
|
+
unref(status).retry ? (openBlock(), createBlock(unref(DouButton), {
|
|
79
|
+
key: 0,
|
|
80
|
+
size: "sm",
|
|
81
|
+
variant: "soft",
|
|
82
|
+
onClick: _cache[0] || (_cache[0] = ($event) => unref(status).retry())
|
|
83
|
+
}, {
|
|
84
|
+
default: withCtx(() => [createTextVNode(toDisplayString(__props.messages.retry), 1)]),
|
|
85
|
+
_: 1
|
|
86
|
+
})) : createCommentVNode("", true)
|
|
87
|
+
])) : unref(status).state === "empty" ? (openBlock(), createElementBlock("div", _hoisted_5, [createVNode(unref(DouEmpty), {
|
|
88
|
+
size: "sm",
|
|
89
|
+
title: unref(status).message || __props.messages.empty
|
|
90
|
+
}, null, 8, ["title"])])) : createCommentVNode("", true)], 8, _hoisted_1);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
export { widget_body_vue_vue_type_script_setup_true_lang_default as default };
|
|
95
|
+
|
|
96
|
+
//# sourceMappingURL=widget-body.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-body.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_unref","_createElementVNode","_createBlock","_resolveDynamicComponent","_toDisplayString","_createVNode","_withCtx","_createTextVNode","_createCommentVNode"],"sources":["../../src/dashboard/widget-body.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { AlertCircleIcon } from '@dou-ui/icons'\nimport { DouButton, DouEmpty, DouSpinner } from 'dou-ui'\nimport { inject, onBeforeUnmount, onMounted, ref } from 'vue'\nimport type { SheetWorkbook } from '@dou-ui/sheet/core'\nimport type { DashboardWidget } from '../core/types'\nimport type { DashboardMessages } from '../locale'\nimport { format } from '../locale'\nimport { provideWidgetContext } from '../widget/context'\nimport { observersKey } from './observers'\nimport type { DashboardWidgetType } from '../widget/define'\n\ndefineOptions({ name: 'DouDashboardWidgetBody' })\n\nconst props = defineProps<{\n widget: DashboardWidget\n type?: DashboardWidgetType<any>\n editing: boolean\n fullscreen?: boolean\n messages: DashboardMessages\n setProps: (id: string, patch: Record<string, unknown>, options?: { group?: string }) => void\n /** Where the widget's workbook goes, for its export menu; the full-screen copy has none. */\n setWorkbook?: (id: string, get: () => SheetWorkbook | undefined) => () => void\n}>()\n\nconst body = ref<HTMLElement>()\nconst width = ref(0)\nconst height = ref(0)\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n // not read here: that would lay the page out once per widget. The first\n // observation comes before the page is painted.\n stop = observers?.size(body.value!, (entry) => {\n width.value = entry.contentRect.width\n height.value = entry.contentRect.height\n })\n})\nonBeforeUnmount(() => stop?.())\nconst { status } = provideWidgetContext({\n widget: () => props.widget,\n editing: () => props.editing,\n fullscreen: () => !!props.fullscreen,\n size: { width, height },\n setProps: props.setProps,\n setWorkbook: props.setWorkbook,\n})\n</script>\n\n<template>\n <div class=\"dou-dashboard__body\" :aria-busy=\"status.state === 'loading' || undefined\">\n <div ref=\"body\" class=\"dou-dashboard__content\">\n <component :is=\"type.component\" v-if=\"type\" />\n <div v-else class=\"dou-dashboard__notice\">\n {{ format(messages.unknownType, { type: widget.type }) }}\n </div>\n </div>\n <div v-if=\"status.state === 'loading'\" class=\"dou-dashboard__status is-loading\" role=\"status\">\n <DouSpinner size=\"sm\" :label=\"messages.loading\" />\n </div>\n <div v-else-if=\"status.state === 'error'\" class=\"dou-dashboard__status is-error\" role=\"alert\">\n <AlertCircleIcon class=\"dou-dashboard__status-icon\" />\n <span>{{ status.message || messages.error }}</span>\n <DouButton v-if=\"status.retry\" size=\"sm\" variant=\"soft\" @click=\"status.retry()\">\n {{ messages.retry }}\n </DouButton>\n </div>\n <div v-else-if=\"status.state === 'empty'\" class=\"dou-dashboard__status is-empty\">\n <DouEmpty size=\"sm\" :title=\"status.message || messages.empty\" />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcA,MAAM,QAAQ;EAWd,MAAM,OAAO,IAAiB;EAC9B,MAAM,QAAQ,IAAI,CAAC;EACnB,MAAM,SAAS,IAAI,CAAC;EACpB,MAAM,YAAY,OAAO,YAAY;EACrC,IAAI;EACJ,gBAAgB;GAGd,OAAO,WAAW,KAAK,KAAK,QAAS,UAAU;IAC7C,MAAM,QAAQ,MAAM,YAAY;IAChC,OAAO,QAAQ,MAAM,YAAY;GACnC,CAAC;EACH,CAAC;EACD,sBAAsB,OAAO,CAAC;EAC9B,MAAM,EAAE,WAAW,qBAAqB;GACtC,cAAc,MAAM;GACpB,eAAe,MAAM;GACrB,kBAAkB,CAAC,CAAC,MAAM;GAC1B,MAAM;IAAE;IAAO;GAAO;GACtB,UAAU,MAAM;GAChB,aAAa,MAAM;EACrB,CAAC;;GAIC,OAAAA,UAAA,GAAAC,mBAoBM,OAAA;IApBD,OAAM;IAAuB,aAAWC,MAAA,MAAA,CAAM,CAAC,UAAK,aAAkB,KAAA;G,IACzEC,mBAKM,OAAA;IALG,SAAA;IAAJ,KAAI;IAAO,OAAM;G,IACkB,QAAA,QAAtCH,UAAA,GAAAI,YAA8CC,wBAA9B,QAAA,KAAK,SAAS,GAAA,EAAA,KAAA,EAAA,CAAA,MAC9BL,UAAA,GAAAC,mBAEM,OAFN,YAEMK,gBADDJ,MAAA,MAAA,CAAM,CAAC,QAAA,SAAS,aAAW,EAAA,MAAU,QAAA,OAAO,KAAI,CAAA,CAAA,GAAA,CAAA,E,SAG5CA,MAAA,MAAA,CAAM,CAAC,UAAK,aAAvBF,UAAA,GAAAC,mBAEM,OAFN,YAEM,CADJM,YAAkDL,MAAA,UAAA,GAAA;IAAtC,MAAK;IAAM,OAAO,QAAA,SAAS;G,4BAEzBA,MAAA,MAAA,CAAM,CAAC,UAAK,WAA5BF,UAAA,GAAAC,mBAMM,OANN,YAMM;IALJM,YAAsDL,MAAA,eAAA,GAAA,EAArC,OAAM,6BAA4B,CAAA;IACnDC,mBAAmD,QAAA,MAAAG,gBAA1CJ,MAAA,MAAA,CAAM,CAAC,WAAW,QAAA,SAAS,KAAK,GAAA,CAAA;IACxBA,MAAA,MAAA,CAAM,CAAC,SAAxBF,UAAA,GAAAI,YAEYF,MAAA,SAAA,GAAA;;KAFmB,MAAK;KAAK,SAAQ;KAAQ,SAAK,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,MAAA,CAAM,CAAC,MAAK;;KAC1E,SAAAM,cAAoB,CAAjBC,gBAAAH,gBAAA,QAAA,SAAS,KAAK,GAAA,CAAA,C;;;G,MAGLJ,MAAA,MAAA,CAAM,CAAC,UAAK,WAA5BF,UAAA,GAAAC,mBAEM,OAFN,YAEM,CADJM,YAAgEL,MAAA,QAAA,GAAA;IAAtD,MAAK;IAAM,OAAOA,MAAA,MAAA,CAAM,CAAC,WAAW,QAAA,SAAS"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import widget_frame_vue_vue_type_script_setup_true_lang_default from "./widget-frame.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
// src/dashboard/widget-frame.vue
|
|
3
|
+
var widget_frame_default = widget_frame_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
export { widget_frame_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=widget-frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-frame.js","names":["_sfc_main"],"sources":["../../src/dashboard/widget-frame.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from '@dou-ui/icons'\nimport {\n DouAlert,\n DouButton,\n DouDropdown,\n DouDropdownItem,\n DouDropdownSub,\n DouEditable,\n DouTag,\n DouTooltip,\n} from 'dou-ui'\nimport type { DropdownValue } from 'dou-ui'\nimport { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport GridLayoutHandle from '../grid/grid-handle.vue'\nimport { format } from '../locale'\nimport { frameContextKey } from './frame-context'\nimport type { WidgetAction } from './frame-context'\nimport { observersKey } from './observers'\nimport WidgetBody from './widget-body.vue'\n\ndefineOptions({ name: 'DouDashboardWidget' })\n\nconst props = defineProps<{ id: string }>()\n\nconst frame = inject(frameContextKey)!\nconst widget = computed(() => frame.widget(props.id))\nconst type = computed(() => widget.value && frame.type(widget.value))\nconst title = computed(() => (widget.value ? frame.title(widget.value) : ''))\nconst editing = computed(() => frame.editing())\nconst messages = computed(() => frame.messages())\n/** The filters this widget set, each with a button to clear it. */\nconst linked = computed(() => frame.linked(props.id))\n/** All of them in one tag (a pivot table's click sets one per field), cleared together. */\nconst linkLabel = computed(() => linked.value.map((link) => link.label).join(' / '))\nfunction clearLinks() {\n for (const link of linked.value) frame.clearFilter(link.key)\n}\n\n/** Others at this widget, when editing together: an outline in the first one's color and their names. */\nconst peers = computed(() => frame.peers(props.id))\nconst peerText = (peer: { name: string; action: string }) => {\n const m = messages.value\n const text =\n peer.action === 'move'\n ? m.peerMoving\n : peer.action === 'resize'\n ? m.peerResizing\n : peer.action === 'settings'\n ? m.peerSettings\n : '{name}'\n return format(text, { name: peer.name })\n}\n\nconst renaming = ref(false)\n\n// Widgets far out of view show only their title until they come near: with\n// hundreds of widgets, their contents and controls are most of the mounting.\nconst root = ref<HTMLElement>()\nconst active = ref(frame.eager(props.id))\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n if (active.value || !observers) {\n active.value = true\n return\n }\n stop = observers.near(root.value!, () => {\n active.value = true\n stop?.()\n })\n})\nonBeforeUnmount(() => stop?.())\n// the dashboard draws everything for an export only when this widget isn't drawn yet\nwatch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true })\nonBeforeUnmount(() => frame.setDrawn(props.id, false))\n// drawn in full to export or print the dashboard, and kept that way\nwatch(\n () => frame.all(),\n (all) => {\n if (!all || active.value) return\n active.value = true\n stop?.()\n },\n { immediate: true },\n)\nconst canFullscreen = computed(() => type.value?.fullscreen !== false)\n\nconst emitAction = (action: WidgetAction) => frame.action(props.id, action)\n\n/** The file types this widget's content can be exported as; none unless it gives a workbook. */\nconst exporters = computed(() => frame.exporters(props.id))\nconst exportError = computed(() => frame.exportError(props.id))\nconst exporting = computed(() => frame.exporting(props.id))\nconst EXPORT = 'export:'\nconst exportOpen = ref(false)\n\nfunction onSelect(value: DropdownValue | undefined) {\n if (typeof value !== 'string') return\n if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(EXPORT.length))\n else emitAction(value as WidgetAction)\n}\n</script>\n\n<template>\n <!-- outside the frame, which cuts off what overflows it -->\n <div v-if=\"widget && peers.length\" class=\"dou-dashboard__peers\" aria-hidden=\"true\">\n <span\n v-for=\"peer in peers\"\n :key=\"`${peer.client}:${peer.action}`\"\n :class=\"['dou-dashboard__peer', `is-${peer.action}`]\"\n :style=\"{ '--dou-dashboard-peer-color': peer.color }\"\n >\n {{ peerText(peer) }}\n </span>\n </div>\n <div\n v-if=\"widget\"\n ref=\"root\"\n :class=\"['dou-dashboard__widget', peers.length && 'has-peers']\"\n :style=\"peers.length ? { '--dou-dashboard-peer-color': peers[0]!.color } : undefined\"\n >\n <template v-if=\"!active\">\n <div class=\"dou-dashboard__header\">\n <div class=\"dou-dashboard__title\">{{ title }}</div>\n </div>\n <div class=\"dou-dashboard__body\" />\n </template>\n <component\n v-else\n :is=\"editing ? GridLayoutHandle : 'div'\"\n :as=\"editing ? 'header' : undefined\"\n class=\"dou-dashboard__header\"\n >\n <DouEditable\n v-if=\"editing\"\n v-model:editing=\"renaming\"\n class=\"dou-dashboard__title\"\n :model-value=\"title\"\n trigger=\"dblclick\"\n select-on-edit\n :aria-label=\"messages.titleField\"\n :data-dou-nodrag=\"renaming ? '' : undefined\"\n @submit=\"(value) => frame.rename(id, value)\"\n />\n <div v-else class=\"dou-dashboard__title\">{{ title }}</div>\n <div v-if=\"linked.length\" class=\"dou-dashboard__links\" data-dou-nodrag>\n <DouTag\n size=\"sm\"\n closable\n :close-label=\"format(messages.clearFilter, { value: linkLabel })\"\n @close=\"clearLinks\"\n >\n {{ format(messages.filteredBy, { value: linkLabel }) }}\n </DouTag>\n </div>\n <div class=\"dou-dashboard__actions\" data-dou-nodrag>\n <DouDropdown v-if=\"editing\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton size=\"sm\" variant=\"ghost\" :aria-label=\"messages.widgetMenu\">\n <MoreHorizontalIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem value=\"settings\">{{ messages.settings }}</DouDropdownItem>\n <DouDropdownItem v-if=\"canFullscreen\" value=\"fullscreen\">\n {{ messages.fullscreen }}\n </DouDropdownItem>\n <DouDropdownSub v-if=\"exporters.length\" :title=\"messages.export\">\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n :disabled=\"exporting\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem value=\"duplicate\" shortcut=\"mod+d\">\n {{ messages.duplicate }}\n </DouDropdownItem>\n <DouDropdownItem value=\"remove\" tone=\"danger\" shortcut=\"delete\" divided>\n {{ messages.remove }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n <DouTooltip\n v-if=\"!editing && exporters.length\"\n :content=\"messages.export\"\n :disabled=\"exportOpen\"\n >\n <span class=\"dou-dashboard__trigger\">\n <DouDropdown v-model:open=\"exportOpen\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.export\"\n :loading=\"exporting\"\n :disabled=\"exporting\"\n >\n <DownloadIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n >\n <template v-if=\"exporter.icon\" #prefix\n ><component :is=\"exporter.icon\"\n /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n </span>\n </DouTooltip>\n <DouTooltip v-if=\"!editing && canFullscreen\" :content=\"messages.fullscreen\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.fullscreen\"\n @click=\"emitAction('fullscreen')\"\n >\n <MaximizeIcon />\n </DouButton>\n </DouTooltip>\n </div>\n </component>\n <div v-if=\"exportError\" class=\"dou-dashboard__export-error\" data-dou-nodrag>\n <DouAlert tone=\"danger\" closable @close=\"frame.clearExportError(id)\">\n {{ exportError }}\n </DouAlert>\n </div>\n <WidgetBody\n v-if=\"active\"\n :widget=\"widget\"\n :type=\"type\"\n :editing=\"editing\"\n :messages=\"messages\"\n :set-props=\"frame.setProps\"\n :set-workbook=\"frame.setWorkbook\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { format } from "../locale.js";
|
|
2
|
+
import grid_handle_default from "../grid/grid-handle.js";
|
|
3
|
+
import { observersKey } from "./observers.js";
|
|
4
|
+
import widget_body_default from "./widget-body.js";
|
|
5
|
+
import { frameContextKey } from "./frame-context.js";
|
|
6
|
+
import { DouAlert, DouButton, DouDropdown, DouDropdownItem, DouDropdownSub, DouEditable, DouTag, DouTooltip } from "dou-ui";
|
|
7
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, resolveDynamicComponent, toDisplayString, unref, watch, withCtx } from "vue";
|
|
8
|
+
import { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from "@dou-ui/icons";
|
|
9
|
+
// src/dashboard/widget-frame.vue?vue&type=script&setup=true&lang.ts
|
|
10
|
+
var _hoisted_1 = {
|
|
11
|
+
key: 0,
|
|
12
|
+
class: "dou-dashboard__peers",
|
|
13
|
+
"aria-hidden": "true"
|
|
14
|
+
};
|
|
15
|
+
var _hoisted_2 = { class: "dou-dashboard__header" };
|
|
16
|
+
var _hoisted_3 = { class: "dou-dashboard__title" };
|
|
17
|
+
var _hoisted_4 = {
|
|
18
|
+
key: 1,
|
|
19
|
+
class: "dou-dashboard__title"
|
|
20
|
+
};
|
|
21
|
+
var _hoisted_5 = {
|
|
22
|
+
key: 2,
|
|
23
|
+
class: "dou-dashboard__links",
|
|
24
|
+
"data-dou-nodrag": ""
|
|
25
|
+
};
|
|
26
|
+
var _hoisted_6 = {
|
|
27
|
+
class: "dou-dashboard__actions",
|
|
28
|
+
"data-dou-nodrag": ""
|
|
29
|
+
};
|
|
30
|
+
var _hoisted_7 = { class: "dou-dashboard__trigger" };
|
|
31
|
+
var _hoisted_8 = {
|
|
32
|
+
key: 2,
|
|
33
|
+
class: "dou-dashboard__export-error",
|
|
34
|
+
"data-dou-nodrag": ""
|
|
35
|
+
};
|
|
36
|
+
var EXPORT = "export:";
|
|
37
|
+
var widget_frame_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
38
|
+
name: "DouDashboardWidget",
|
|
39
|
+
__name: "widget-frame",
|
|
40
|
+
props: { id: {} },
|
|
41
|
+
setup(__props) {
|
|
42
|
+
const props = __props;
|
|
43
|
+
const frame = inject(frameContextKey);
|
|
44
|
+
const widget = computed(() => frame.widget(props.id));
|
|
45
|
+
const type = computed(() => widget.value && frame.type(widget.value));
|
|
46
|
+
const title = computed(() => widget.value ? frame.title(widget.value) : "");
|
|
47
|
+
const editing = computed(() => frame.editing());
|
|
48
|
+
const messages = computed(() => frame.messages());
|
|
49
|
+
/** The filters this widget set, each with a button to clear it. */
|
|
50
|
+
const linked = computed(() => frame.linked(props.id));
|
|
51
|
+
/** All of them in one tag (a pivot table's click sets one per field), cleared together. */
|
|
52
|
+
const linkLabel = computed(() => linked.value.map((link) => link.label).join(" / "));
|
|
53
|
+
function clearLinks() {
|
|
54
|
+
for (const link of linked.value) frame.clearFilter(link.key);
|
|
55
|
+
}
|
|
56
|
+
/** Others at this widget, when editing together: an outline in the first one's color and their names. */
|
|
57
|
+
const peers = computed(() => frame.peers(props.id));
|
|
58
|
+
const peerText = (peer) => {
|
|
59
|
+
const m = messages.value;
|
|
60
|
+
const text = peer.action === "move" ? m.peerMoving : peer.action === "resize" ? m.peerResizing : peer.action === "settings" ? m.peerSettings : "{name}";
|
|
61
|
+
return format(text, { name: peer.name });
|
|
62
|
+
};
|
|
63
|
+
const renaming = ref(false);
|
|
64
|
+
const root = ref();
|
|
65
|
+
const active = ref(frame.eager(props.id));
|
|
66
|
+
const observers = inject(observersKey);
|
|
67
|
+
let stop;
|
|
68
|
+
onMounted(() => {
|
|
69
|
+
if (active.value || !observers) {
|
|
70
|
+
active.value = true;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
stop = observers.near(root.value, () => {
|
|
74
|
+
active.value = true;
|
|
75
|
+
stop?.();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
onBeforeUnmount(() => stop?.());
|
|
79
|
+
watch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true });
|
|
80
|
+
onBeforeUnmount(() => frame.setDrawn(props.id, false));
|
|
81
|
+
watch(() => frame.all(), (all) => {
|
|
82
|
+
if (!all || active.value) return;
|
|
83
|
+
active.value = true;
|
|
84
|
+
stop?.();
|
|
85
|
+
}, { immediate: true });
|
|
86
|
+
const canFullscreen = computed(() => type.value?.fullscreen !== false);
|
|
87
|
+
const emitAction = (action) => frame.action(props.id, action);
|
|
88
|
+
/** The file types this widget's content can be exported as; none unless it gives a workbook. */
|
|
89
|
+
const exporters = computed(() => frame.exporters(props.id));
|
|
90
|
+
const exportError = computed(() => frame.exportError(props.id));
|
|
91
|
+
const exporting = computed(() => frame.exporting(props.id));
|
|
92
|
+
const exportOpen = ref(false);
|
|
93
|
+
function onSelect(value) {
|
|
94
|
+
if (typeof value !== "string") return;
|
|
95
|
+
if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(7));
|
|
96
|
+
else emitAction(value);
|
|
97
|
+
}
|
|
98
|
+
return (_ctx, _cache) => {
|
|
99
|
+
return openBlock(), createElementBlock(Fragment, null, [widget.value && peers.value.length ? (openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(peers.value, (peer) => {
|
|
100
|
+
return openBlock(), createElementBlock("span", {
|
|
101
|
+
key: `${peer.client}:${peer.action}`,
|
|
102
|
+
class: normalizeClass(["dou-dashboard__peer", `is-${peer.action}`]),
|
|
103
|
+
style: normalizeStyle({ "--dou-dashboard-peer-color": peer.color })
|
|
104
|
+
}, toDisplayString(peerText(peer)), 7);
|
|
105
|
+
}), 128))])) : createCommentVNode("", true), widget.value ? (openBlock(), createElementBlock("div", {
|
|
106
|
+
key: 1,
|
|
107
|
+
ref_key: "root",
|
|
108
|
+
ref: root,
|
|
109
|
+
class: normalizeClass(["dou-dashboard__widget", peers.value.length && "has-peers"]),
|
|
110
|
+
style: normalizeStyle(peers.value.length ? { "--dou-dashboard-peer-color": peers.value[0].color } : void 0)
|
|
111
|
+
}, [
|
|
112
|
+
!active.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("div", _hoisted_2, [createElementVNode("div", _hoisted_3, toDisplayString(title.value), 1)]), _cache[5] || (_cache[5] = createElementVNode("div", { class: "dou-dashboard__body" }, null, -1))], 64)) : (openBlock(), createBlock(resolveDynamicComponent(editing.value ? grid_handle_default : "div"), {
|
|
113
|
+
key: 1,
|
|
114
|
+
as: editing.value ? "header" : void 0,
|
|
115
|
+
class: "dou-dashboard__header"
|
|
116
|
+
}, {
|
|
117
|
+
default: withCtx(() => [
|
|
118
|
+
editing.value ? (openBlock(), createBlock(unref(DouEditable), {
|
|
119
|
+
key: 0,
|
|
120
|
+
editing: renaming.value,
|
|
121
|
+
"onUpdate:editing": _cache[0] || (_cache[0] = ($event) => renaming.value = $event),
|
|
122
|
+
class: "dou-dashboard__title",
|
|
123
|
+
"model-value": title.value,
|
|
124
|
+
trigger: "dblclick",
|
|
125
|
+
"select-on-edit": "",
|
|
126
|
+
"aria-label": messages.value.titleField,
|
|
127
|
+
"data-dou-nodrag": renaming.value ? "" : void 0,
|
|
128
|
+
onSubmit: _cache[1] || (_cache[1] = (value) => unref(frame).rename(__props.id, value))
|
|
129
|
+
}, null, 8, [
|
|
130
|
+
"editing",
|
|
131
|
+
"model-value",
|
|
132
|
+
"aria-label",
|
|
133
|
+
"data-dou-nodrag"
|
|
134
|
+
])) : (openBlock(), createElementBlock("div", _hoisted_4, toDisplayString(title.value), 1)),
|
|
135
|
+
linked.value.length ? (openBlock(), createElementBlock("div", _hoisted_5, [createVNode(unref(DouTag), {
|
|
136
|
+
size: "sm",
|
|
137
|
+
closable: "",
|
|
138
|
+
"close-label": unref(format)(messages.value.clearFilter, { value: linkLabel.value }),
|
|
139
|
+
onClose: clearLinks
|
|
140
|
+
}, {
|
|
141
|
+
default: withCtx(() => [createTextVNode(toDisplayString(unref(format)(messages.value.filteredBy, { value: linkLabel.value })), 1)]),
|
|
142
|
+
_: 1
|
|
143
|
+
}, 8, ["close-label"])])) : createCommentVNode("", true),
|
|
144
|
+
createElementVNode("div", _hoisted_6, [
|
|
145
|
+
editing.value ? (openBlock(), createBlock(unref(DouDropdown), {
|
|
146
|
+
key: 0,
|
|
147
|
+
placement: "bottom-end",
|
|
148
|
+
onSelect
|
|
149
|
+
}, {
|
|
150
|
+
menu: withCtx(() => [
|
|
151
|
+
createVNode(unref(DouDropdownItem), { value: "settings" }, {
|
|
152
|
+
default: withCtx(() => [createTextVNode(toDisplayString(messages.value.settings), 1)]),
|
|
153
|
+
_: 1
|
|
154
|
+
}),
|
|
155
|
+
canFullscreen.value ? (openBlock(), createBlock(unref(DouDropdownItem), {
|
|
156
|
+
key: 0,
|
|
157
|
+
value: "fullscreen"
|
|
158
|
+
}, {
|
|
159
|
+
default: withCtx(() => [createTextVNode(toDisplayString(messages.value.fullscreen), 1)]),
|
|
160
|
+
_: 1
|
|
161
|
+
})) : createCommentVNode("", true),
|
|
162
|
+
exporters.value.length ? (openBlock(), createBlock(unref(DouDropdownSub), {
|
|
163
|
+
key: 1,
|
|
164
|
+
title: messages.value.export
|
|
165
|
+
}, {
|
|
166
|
+
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(exporters.value, (exporter) => {
|
|
167
|
+
return openBlock(), createBlock(unref(DouDropdownItem), {
|
|
168
|
+
key: exporter.name,
|
|
169
|
+
value: EXPORT + exporter.name,
|
|
170
|
+
disabled: exporting.value
|
|
171
|
+
}, createSlots({
|
|
172
|
+
default: withCtx(() => [createTextVNode(" " + toDisplayString(exporter.label), 1)]),
|
|
173
|
+
_: 2
|
|
174
|
+
}, [exporter.icon ? {
|
|
175
|
+
name: "prefix",
|
|
176
|
+
fn: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(exporter.icon)))]),
|
|
177
|
+
key: "0"
|
|
178
|
+
} : void 0]), 1032, ["value", "disabled"]);
|
|
179
|
+
}), 128))]),
|
|
180
|
+
_: 1
|
|
181
|
+
}, 8, ["title"])) : createCommentVNode("", true),
|
|
182
|
+
createVNode(unref(DouDropdownItem), {
|
|
183
|
+
value: "duplicate",
|
|
184
|
+
shortcut: "mod+d"
|
|
185
|
+
}, {
|
|
186
|
+
default: withCtx(() => [createTextVNode(toDisplayString(messages.value.duplicate), 1)]),
|
|
187
|
+
_: 1
|
|
188
|
+
}),
|
|
189
|
+
createVNode(unref(DouDropdownItem), {
|
|
190
|
+
value: "remove",
|
|
191
|
+
tone: "danger",
|
|
192
|
+
shortcut: "delete",
|
|
193
|
+
divided: ""
|
|
194
|
+
}, {
|
|
195
|
+
default: withCtx(() => [createTextVNode(toDisplayString(messages.value.remove), 1)]),
|
|
196
|
+
_: 1
|
|
197
|
+
})
|
|
198
|
+
]),
|
|
199
|
+
default: withCtx(() => [createVNode(unref(DouButton), {
|
|
200
|
+
size: "sm",
|
|
201
|
+
variant: "ghost",
|
|
202
|
+
"aria-label": messages.value.widgetMenu
|
|
203
|
+
}, {
|
|
204
|
+
default: withCtx(() => [createVNode(unref(MoreHorizontalIcon))]),
|
|
205
|
+
_: 1
|
|
206
|
+
}, 8, ["aria-label"])]),
|
|
207
|
+
_: 1
|
|
208
|
+
})) : createCommentVNode("", true),
|
|
209
|
+
!editing.value && exporters.value.length ? (openBlock(), createBlock(unref(DouTooltip), {
|
|
210
|
+
key: 1,
|
|
211
|
+
content: messages.value.export,
|
|
212
|
+
disabled: exportOpen.value
|
|
213
|
+
}, {
|
|
214
|
+
default: withCtx(() => [createElementVNode("span", _hoisted_7, [createVNode(unref(DouDropdown), {
|
|
215
|
+
open: exportOpen.value,
|
|
216
|
+
"onUpdate:open": _cache[2] || (_cache[2] = ($event) => exportOpen.value = $event),
|
|
217
|
+
placement: "bottom-end",
|
|
218
|
+
onSelect
|
|
219
|
+
}, {
|
|
220
|
+
menu: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(exporters.value, (exporter) => {
|
|
221
|
+
return openBlock(), createBlock(unref(DouDropdownItem), {
|
|
222
|
+
key: exporter.name,
|
|
223
|
+
value: EXPORT + exporter.name
|
|
224
|
+
}, createSlots({
|
|
225
|
+
default: withCtx(() => [createTextVNode(" " + toDisplayString(exporter.label), 1)]),
|
|
226
|
+
_: 2
|
|
227
|
+
}, [exporter.icon ? {
|
|
228
|
+
name: "prefix",
|
|
229
|
+
fn: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(exporter.icon)))]),
|
|
230
|
+
key: "0"
|
|
231
|
+
} : void 0]), 1032, ["value"]);
|
|
232
|
+
}), 128))]),
|
|
233
|
+
default: withCtx(() => [createVNode(unref(DouButton), {
|
|
234
|
+
size: "sm",
|
|
235
|
+
variant: "ghost",
|
|
236
|
+
"aria-label": messages.value.export,
|
|
237
|
+
loading: exporting.value,
|
|
238
|
+
disabled: exporting.value
|
|
239
|
+
}, {
|
|
240
|
+
default: withCtx(() => [createVNode(unref(DownloadIcon))]),
|
|
241
|
+
_: 1
|
|
242
|
+
}, 8, [
|
|
243
|
+
"aria-label",
|
|
244
|
+
"loading",
|
|
245
|
+
"disabled"
|
|
246
|
+
])]),
|
|
247
|
+
_: 1
|
|
248
|
+
}, 8, ["open"])])]),
|
|
249
|
+
_: 1
|
|
250
|
+
}, 8, ["content", "disabled"])) : createCommentVNode("", true),
|
|
251
|
+
!editing.value && canFullscreen.value ? (openBlock(), createBlock(unref(DouTooltip), {
|
|
252
|
+
key: 2,
|
|
253
|
+
content: messages.value.fullscreen
|
|
254
|
+
}, {
|
|
255
|
+
default: withCtx(() => [createVNode(unref(DouButton), {
|
|
256
|
+
size: "sm",
|
|
257
|
+
variant: "ghost",
|
|
258
|
+
"aria-label": messages.value.fullscreen,
|
|
259
|
+
onClick: _cache[3] || (_cache[3] = ($event) => emitAction("fullscreen"))
|
|
260
|
+
}, {
|
|
261
|
+
default: withCtx(() => [createVNode(unref(MaximizeIcon))]),
|
|
262
|
+
_: 1
|
|
263
|
+
}, 8, ["aria-label"])]),
|
|
264
|
+
_: 1
|
|
265
|
+
}, 8, ["content"])) : createCommentVNode("", true)
|
|
266
|
+
])
|
|
267
|
+
]),
|
|
268
|
+
_: 1
|
|
269
|
+
}, 8, ["as"])),
|
|
270
|
+
exportError.value ? (openBlock(), createElementBlock("div", _hoisted_8, [createVNode(unref(DouAlert), {
|
|
271
|
+
tone: "danger",
|
|
272
|
+
closable: "",
|
|
273
|
+
onClose: _cache[4] || (_cache[4] = ($event) => unref(frame).clearExportError(__props.id))
|
|
274
|
+
}, {
|
|
275
|
+
default: withCtx(() => [createTextVNode(toDisplayString(exportError.value), 1)]),
|
|
276
|
+
_: 1
|
|
277
|
+
})])) : createCommentVNode("", true),
|
|
278
|
+
active.value ? (openBlock(), createBlock(widget_body_default, {
|
|
279
|
+
key: 3,
|
|
280
|
+
widget: widget.value,
|
|
281
|
+
type: type.value,
|
|
282
|
+
editing: editing.value,
|
|
283
|
+
messages: messages.value,
|
|
284
|
+
"set-props": unref(frame).setProps,
|
|
285
|
+
"set-workbook": unref(frame).setWorkbook
|
|
286
|
+
}, null, 8, [
|
|
287
|
+
"widget",
|
|
288
|
+
"type",
|
|
289
|
+
"editing",
|
|
290
|
+
"messages",
|
|
291
|
+
"set-props",
|
|
292
|
+
"set-workbook"
|
|
293
|
+
])) : createCommentVNode("", true)
|
|
294
|
+
], 6)) : createCommentVNode("", true)], 64);
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
export { widget_frame_vue_vue_type_script_setup_true_lang_default as default };
|
|
299
|
+
|
|
300
|
+
//# sourceMappingURL=widget-frame.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-frame.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_renderList","_normalizeClass","_normalizeStyle","_toDisplayString","_createCommentVNode","_createElementVNode","_createBlock","_resolveDynamicComponent","GridLayoutHandle","_withCtx","_unref","_createVNode","_createTextVNode","_createSlots","WidgetBody"],"sources":["../../src/dashboard/widget-frame.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DownloadIcon, MaximizeIcon, MoreHorizontalIcon } from '@dou-ui/icons'\nimport {\n DouAlert,\n DouButton,\n DouDropdown,\n DouDropdownItem,\n DouDropdownSub,\n DouEditable,\n DouTag,\n DouTooltip,\n} from 'dou-ui'\nimport type { DropdownValue } from 'dou-ui'\nimport { computed, inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport GridLayoutHandle from '../grid/grid-handle.vue'\nimport { format } from '../locale'\nimport { frameContextKey } from './frame-context'\nimport type { WidgetAction } from './frame-context'\nimport { observersKey } from './observers'\nimport WidgetBody from './widget-body.vue'\n\ndefineOptions({ name: 'DouDashboardWidget' })\n\nconst props = defineProps<{ id: string }>()\n\nconst frame = inject(frameContextKey)!\nconst widget = computed(() => frame.widget(props.id))\nconst type = computed(() => widget.value && frame.type(widget.value))\nconst title = computed(() => (widget.value ? frame.title(widget.value) : ''))\nconst editing = computed(() => frame.editing())\nconst messages = computed(() => frame.messages())\n/** The filters this widget set, each with a button to clear it. */\nconst linked = computed(() => frame.linked(props.id))\n/** All of them in one tag (a pivot table's click sets one per field), cleared together. */\nconst linkLabel = computed(() => linked.value.map((link) => link.label).join(' / '))\nfunction clearLinks() {\n for (const link of linked.value) frame.clearFilter(link.key)\n}\n\n/** Others at this widget, when editing together: an outline in the first one's color and their names. */\nconst peers = computed(() => frame.peers(props.id))\nconst peerText = (peer: { name: string; action: string }) => {\n const m = messages.value\n const text =\n peer.action === 'move'\n ? m.peerMoving\n : peer.action === 'resize'\n ? m.peerResizing\n : peer.action === 'settings'\n ? m.peerSettings\n : '{name}'\n return format(text, { name: peer.name })\n}\n\nconst renaming = ref(false)\n\n// Widgets far out of view show only their title until they come near: with\n// hundreds of widgets, their contents and controls are most of the mounting.\nconst root = ref<HTMLElement>()\nconst active = ref(frame.eager(props.id))\nconst observers = inject(observersKey)\nlet stop: (() => void) | undefined\nonMounted(() => {\n if (active.value || !observers) {\n active.value = true\n return\n }\n stop = observers.near(root.value!, () => {\n active.value = true\n stop?.()\n })\n})\nonBeforeUnmount(() => stop?.())\n// the dashboard draws everything for an export only when this widget isn't drawn yet\nwatch(active, (drawn) => frame.setDrawn(props.id, drawn), { immediate: true })\nonBeforeUnmount(() => frame.setDrawn(props.id, false))\n// drawn in full to export or print the dashboard, and kept that way\nwatch(\n () => frame.all(),\n (all) => {\n if (!all || active.value) return\n active.value = true\n stop?.()\n },\n { immediate: true },\n)\nconst canFullscreen = computed(() => type.value?.fullscreen !== false)\n\nconst emitAction = (action: WidgetAction) => frame.action(props.id, action)\n\n/** The file types this widget's content can be exported as; none unless it gives a workbook. */\nconst exporters = computed(() => frame.exporters(props.id))\nconst exportError = computed(() => frame.exportError(props.id))\nconst exporting = computed(() => frame.exporting(props.id))\nconst EXPORT = 'export:'\nconst exportOpen = ref(false)\n\nfunction onSelect(value: DropdownValue | undefined) {\n if (typeof value !== 'string') return\n if (value.startsWith(EXPORT)) frame.exportTo(props.id, value.slice(EXPORT.length))\n else emitAction(value as WidgetAction)\n}\n</script>\n\n<template>\n <!-- outside the frame, which cuts off what overflows it -->\n <div v-if=\"widget && peers.length\" class=\"dou-dashboard__peers\" aria-hidden=\"true\">\n <span\n v-for=\"peer in peers\"\n :key=\"`${peer.client}:${peer.action}`\"\n :class=\"['dou-dashboard__peer', `is-${peer.action}`]\"\n :style=\"{ '--dou-dashboard-peer-color': peer.color }\"\n >\n {{ peerText(peer) }}\n </span>\n </div>\n <div\n v-if=\"widget\"\n ref=\"root\"\n :class=\"['dou-dashboard__widget', peers.length && 'has-peers']\"\n :style=\"peers.length ? { '--dou-dashboard-peer-color': peers[0]!.color } : undefined\"\n >\n <template v-if=\"!active\">\n <div class=\"dou-dashboard__header\">\n <div class=\"dou-dashboard__title\">{{ title }}</div>\n </div>\n <div class=\"dou-dashboard__body\" />\n </template>\n <component\n v-else\n :is=\"editing ? GridLayoutHandle : 'div'\"\n :as=\"editing ? 'header' : undefined\"\n class=\"dou-dashboard__header\"\n >\n <DouEditable\n v-if=\"editing\"\n v-model:editing=\"renaming\"\n class=\"dou-dashboard__title\"\n :model-value=\"title\"\n trigger=\"dblclick\"\n select-on-edit\n :aria-label=\"messages.titleField\"\n :data-dou-nodrag=\"renaming ? '' : undefined\"\n @submit=\"(value) => frame.rename(id, value)\"\n />\n <div v-else class=\"dou-dashboard__title\">{{ title }}</div>\n <div v-if=\"linked.length\" class=\"dou-dashboard__links\" data-dou-nodrag>\n <DouTag\n size=\"sm\"\n closable\n :close-label=\"format(messages.clearFilter, { value: linkLabel })\"\n @close=\"clearLinks\"\n >\n {{ format(messages.filteredBy, { value: linkLabel }) }}\n </DouTag>\n </div>\n <div class=\"dou-dashboard__actions\" data-dou-nodrag>\n <DouDropdown v-if=\"editing\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton size=\"sm\" variant=\"ghost\" :aria-label=\"messages.widgetMenu\">\n <MoreHorizontalIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem value=\"settings\">{{ messages.settings }}</DouDropdownItem>\n <DouDropdownItem v-if=\"canFullscreen\" value=\"fullscreen\">\n {{ messages.fullscreen }}\n </DouDropdownItem>\n <DouDropdownSub v-if=\"exporters.length\" :title=\"messages.export\">\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n :disabled=\"exporting\"\n >\n <template v-if=\"exporter.icon\" #prefix><component :is=\"exporter.icon\" /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </DouDropdownSub>\n <DouDropdownItem value=\"duplicate\" shortcut=\"mod+d\">\n {{ messages.duplicate }}\n </DouDropdownItem>\n <DouDropdownItem value=\"remove\" tone=\"danger\" shortcut=\"delete\" divided>\n {{ messages.remove }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n <DouTooltip\n v-if=\"!editing && exporters.length\"\n :content=\"messages.export\"\n :disabled=\"exportOpen\"\n >\n <span class=\"dou-dashboard__trigger\">\n <DouDropdown v-model:open=\"exportOpen\" placement=\"bottom-end\" @select=\"onSelect\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.export\"\n :loading=\"exporting\"\n :disabled=\"exporting\"\n >\n <DownloadIcon />\n </DouButton>\n <template #menu>\n <DouDropdownItem\n v-for=\"exporter in exporters\"\n :key=\"exporter.name\"\n :value=\"EXPORT + exporter.name\"\n >\n <template v-if=\"exporter.icon\" #prefix\n ><component :is=\"exporter.icon\"\n /></template>\n {{ exporter.label }}\n </DouDropdownItem>\n </template>\n </DouDropdown>\n </span>\n </DouTooltip>\n <DouTooltip v-if=\"!editing && canFullscreen\" :content=\"messages.fullscreen\">\n <DouButton\n size=\"sm\"\n variant=\"ghost\"\n :aria-label=\"messages.fullscreen\"\n @click=\"emitAction('fullscreen')\"\n >\n <MaximizeIcon />\n </DouButton>\n </DouTooltip>\n </div>\n </component>\n <div v-if=\"exportError\" class=\"dou-dashboard__export-error\" data-dou-nodrag>\n <DouAlert tone=\"danger\" closable @close=\"frame.clearExportError(id)\">\n {{ exportError }}\n </DouAlert>\n </div>\n <WidgetBody\n v-if=\"active\"\n :widget=\"widget\"\n :type=\"type\"\n :editing=\"editing\"\n :messages=\"messages\"\n :set-props=\"frame.setProps\"\n :set-workbook=\"frame.setWorkbook\"\n />\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import widget_settings_vue_vue_type_script_setup_true_lang_default from "./widget-settings.vue_vue_type_script_setup_true_lang.js";
|
|
2
|
+
// src/dashboard/widget-settings.vue
|
|
3
|
+
var widget_settings_default = widget_settings_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
export { widget_settings_default as default };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=widget-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-settings.js","names":["_sfc_main"],"sources":["../../src/dashboard/widget-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { DashboardWidget } from '../core/types'\nimport { provideWidgetContext } from '../widget/context'\nimport type { DashboardWidgetType } from '../widget/define'\n\ndefineOptions({ name: 'DouDashboardWidgetSettings' })\n\nconst props = defineProps<{\n widget: DashboardWidget\n type: DashboardWidgetType<any>\n setProps: (id: string, patch: Record<string, unknown>, options?: { group?: string }) => void\n}>()\nconst emit = defineEmits<{ 'update:props': [props: Record<string, unknown>] }>()\n\n// the settings form can read the widget the same way its content does\nprovideWidgetContext({\n widget: () => props.widget,\n editing: () => true,\n fullscreen: () => false,\n size: { width: ref(0), height: ref(0) },\n setProps: props.setProps,\n})\n</script>\n\n<template>\n <component\n :is=\"type.settings\"\n :model-value=\"widget.props ?? {}\"\n @update:model-value=\"(value: Record<string, unknown>) => emit('update:props', value)\"\n />\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { provideWidgetContext } from "../widget/context.js";
|
|
2
|
+
import { createBlock, defineComponent, openBlock, ref, resolveDynamicComponent } from "vue";
|
|
3
|
+
// src/dashboard/widget-settings.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var widget_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
5
|
+
name: "DouDashboardWidgetSettings",
|
|
6
|
+
__name: "widget-settings",
|
|
7
|
+
props: {
|
|
8
|
+
widget: {},
|
|
9
|
+
type: {},
|
|
10
|
+
setProps: { type: Function }
|
|
11
|
+
},
|
|
12
|
+
emits: ["update:props"],
|
|
13
|
+
setup(__props, { emit: __emit }) {
|
|
14
|
+
const props = __props;
|
|
15
|
+
const emit = __emit;
|
|
16
|
+
provideWidgetContext({
|
|
17
|
+
widget: () => props.widget,
|
|
18
|
+
editing: () => true,
|
|
19
|
+
fullscreen: () => false,
|
|
20
|
+
size: {
|
|
21
|
+
width: ref(0),
|
|
22
|
+
height: ref(0)
|
|
23
|
+
},
|
|
24
|
+
setProps: props.setProps
|
|
25
|
+
});
|
|
26
|
+
return (_ctx, _cache) => {
|
|
27
|
+
return openBlock(), createBlock(resolveDynamicComponent(__props.type.settings), {
|
|
28
|
+
"model-value": __props.widget.props ?? {},
|
|
29
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = (value) => emit("update:props", value))
|
|
30
|
+
}, null, 8, ["model-value"]);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
export { widget_settings_vue_vue_type_script_setup_true_lang_default as default };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=widget-settings.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-settings.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_resolveDynamicComponent"],"sources":["../../src/dashboard/widget-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport type { DashboardWidget } from '../core/types'\nimport { provideWidgetContext } from '../widget/context'\nimport type { DashboardWidgetType } from '../widget/define'\n\ndefineOptions({ name: 'DouDashboardWidgetSettings' })\n\nconst props = defineProps<{\n widget: DashboardWidget\n type: DashboardWidgetType<any>\n setProps: (id: string, patch: Record<string, unknown>, options?: { group?: string }) => void\n}>()\nconst emit = defineEmits<{ 'update:props': [props: Record<string, unknown>] }>()\n\n// the settings form can read the widget the same way its content does\nprovideWidgetContext({\n widget: () => props.widget,\n editing: () => true,\n fullscreen: () => false,\n size: { width: ref(0), height: ref(0) },\n setProps: props.setProps,\n})\n</script>\n\n<template>\n <component\n :is=\"type.settings\"\n :model-value=\"widget.props ?? {}\"\n @update:model-value=\"(value: Record<string, unknown>) => emit('update:props', value)\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;EAQA,MAAM,QAAQ;EAKd,MAAM,OAAO;EAGb,qBAAqB;GACnB,cAAc,MAAM;GACpB,eAAe;GACf,kBAAkB;GAClB,MAAM;IAAE,OAAO,IAAI,CAAC;IAAG,QAAQ,IAAI,CAAC;GAAE;GACtC,UAAU,MAAM;EAClB,CAAC;;GAIC,OAAAA,UAAA,GAAAC,YAIEC,wBAHK,QAAA,KAAK,QAAQ,GAAA;IACjB,eAAa,QAAA,OAAO,SAAK,CAAA;IACzB,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAmC,KAAI,gBAAiB,KAAK"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../../src/data/context.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\nimport type { SourceStore } from './store'\nimport type { DashboardFilters, DashboardLinkedFilter, DashboardSetFilterOptions } from './types'\n\n/** What widgets read from their dashboard about data and filters. */\nexport interface DataContext {\n store: SourceStore\n /** The names of the dashboard's sources. */\n sourceNames: () => string[]\n /** Every filter value, as bound with `v-model:filters`. */\n filters: () => DashboardFilters\n /** The keys of the filters a widget set itself, which it doesn't see. */\n emitted: (id: string) => ReadonlySet<string>\n /** The filters a widget set itself, for its title bar. */\n linked: (id: string) => DashboardLinkedFilter[]\n /** Sets (or clears, with an empty value) a filter; `widget` is the widget setting it, if any. */\n setFilter: (\n widget: string | undefined,\n key: string,\n value: unknown,\n options?: DashboardSetFilterOptions,\n ) => void\n}\n\nexport const dataContextKey: InjectionKey<DataContext> = Symbol('dou-dashboard-data')\n"],"mappings":";AAwBA,IAAa,iBAA4C,OAAO,oBAAoB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/data/filters.ts
|
|
2
|
+
/** Whether a filter value filters nothing: `undefined`, `null`, `''` or an empty array. */
|
|
3
|
+
function isEmptyFilter(value) {
|
|
4
|
+
return value === void 0 || value === null || value === "" || Array.isArray(value) && value.every(isEmptyFilter);
|
|
5
|
+
}
|
|
6
|
+
/** The filters without empty values and without `skip`, limited to `keys` when given. */
|
|
7
|
+
function pickFilters(filters, keys, skip) {
|
|
8
|
+
const result = {};
|
|
9
|
+
for (const key of keys ?? Object.keys(filters)) {
|
|
10
|
+
const value = filters[key];
|
|
11
|
+
if (!skip?.has(key) && !isEmptyFilter(value)) result[key] = value;
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
/** JSON with object keys in order, so equal filters give equal text. */
|
|
16
|
+
function stableKey(value) {
|
|
17
|
+
if (Array.isArray(value)) return `[${value.map(stableKey).join(",")}]`;
|
|
18
|
+
if (value && typeof value === "object") {
|
|
19
|
+
if (value instanceof Date) return JSON.stringify(value);
|
|
20
|
+
return `{${Object.keys(value).sort().filter((key) => value[key] !== void 0).map((key) => `${JSON.stringify(key)}:${stableKey(value[key])}`).join(",")}}`;
|
|
21
|
+
}
|
|
22
|
+
return value === void 0 ? "null" : JSON.stringify(value);
|
|
23
|
+
}
|
|
24
|
+
/** How a filter value reads when no label is given: lists joined with `、`. */
|
|
25
|
+
function filterText(value) {
|
|
26
|
+
if (Array.isArray(value)) return value.map(filterText).join("、");
|
|
27
|
+
return value == null ? "" : String(value);
|
|
28
|
+
}
|
|
29
|
+
export { filterText, isEmptyFilter, pickFilters, stableKey };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=filters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filters.js","names":[],"sources":["../../src/data/filters.ts"],"sourcesContent":["import type { DashboardFilters } from './types'\n\n/** Whether a filter value filters nothing: `undefined`, `null`, `''` or an empty array. */\nexport function isEmptyFilter(value: unknown) {\n return (\n value === undefined ||\n value === null ||\n value === '' ||\n (Array.isArray(value) && value.every(isEmptyFilter))\n )\n}\n\n/** The filters without empty values and without `skip`, limited to `keys` when given. */\nexport function pickFilters(\n filters: DashboardFilters,\n keys?: readonly string[],\n skip?: ReadonlySet<string>,\n): DashboardFilters {\n const result: DashboardFilters = {}\n for (const key of keys ?? Object.keys(filters)) {\n const value = filters[key]\n if (!skip?.has(key) && !isEmptyFilter(value)) result[key] = value\n }\n return result\n}\n\n/** JSON with object keys in order, so equal filters give equal text. */\nexport function stableKey(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(stableKey).join(',')}]`\n if (value && typeof value === 'object') {\n if (value instanceof Date) return JSON.stringify(value)\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n const keys = Object.keys(value).sort()\n return `{${keys\n .filter((key) => (value as Record<string, unknown>)[key] !== undefined)\n .map((key) => `${JSON.stringify(key)}:${stableKey((value as Record<string, unknown>)[key])}`)\n .join(',')}}`\n }\n return value === undefined ? 'null' : JSON.stringify(value)\n}\n\n/** How a filter value reads when no label is given: lists joined with `、`. */\nexport function filterText(value: unknown): string {\n if (Array.isArray(value)) return value.map(filterText).join('、')\n return value == null ? '' : String(value)\n}\n"],"mappings":";;AAGA,SAAgB,cAAc,OAAgB;CAC5C,OACE,UAAU,KAAA,KACV,UAAU,QACV,UAAU,MACT,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,aAAa;AAEtD;;AAGA,SAAgB,YACd,SACA,MACA,MACkB;CAClB,MAAM,SAA2B,CAAC;CAClC,KAAK,MAAM,OAAO,QAAQ,OAAO,KAAK,OAAO,GAAG;EAC9C,MAAM,QAAQ,QAAQ;EACtB,IAAI,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,KAAK,GAAG,OAAO,OAAO;CAC9D;CACA,OAAO;AACT;;AAGA,SAAgB,UAAU,OAAwB;CAChD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,SAAS,CAAC,CAAC,KAAK,GAAG,EAAE;CACpE,IAAI,SAAS,OAAO,UAAU,UAAU;EACtC,IAAI,iBAAiB,MAAM,OAAO,KAAK,UAAU,KAAK;EAGtD,OAAO,IADM,OAAO,KAAK,KAAK,CAAC,CAAC,KACrB,CAAA,CACR,QAAQ,QAAS,MAAkC,SAAS,KAAA,CAAS,CAAC,CACtE,KAAK,QAAQ,GAAG,KAAK,UAAU,GAAG,EAAE,GAAG,UAAW,MAAkC,IAAI,GAAG,CAAC,CAC5F,KAAK,GAAG,EAAE;CACf;CACA,OAAO,UAAU,KAAA,IAAY,SAAS,KAAK,UAAU,KAAK;AAC5D;;AAGA,SAAgB,WAAW,OAAwB;CACjD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,UAAU,CAAC,CAAC,KAAK,GAAG;CAC/D,OAAO,SAAS,OAAO,KAAK,OAAO,KAAK;AAC1C"}
|