@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.
Files changed (188) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/chart/chart-settings.js +6 -0
  4. package/dist/chart/chart-settings.js.map +1 -0
  5. package/dist/chart/chart-settings.vue_vue_type_script_setup_true_lang.js +122 -0
  6. package/dist/chart/chart-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  7. package/dist/chart/chart.js +6 -0
  8. package/dist/chart/chart.js.map +1 -0
  9. package/dist/chart/chart.vue_vue_type_script_setup_true_lang.js +99 -0
  10. package/dist/chart/chart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/chart/index.js +33 -0
  12. package/dist/chart/index.js.map +1 -0
  13. package/dist/collaboration/index.js +281 -0
  14. package/dist/collaboration/index.js.map +1 -0
  15. package/dist/collaboration/order.js +88 -0
  16. package/dist/collaboration/order.js.map +1 -0
  17. package/dist/core/document.js +128 -0
  18. package/dist/core/document.js.map +1 -0
  19. package/dist/core/history.js +66 -0
  20. package/dist/core/history.js.map +1 -0
  21. package/dist/core/transaction.js +218 -0
  22. package/dist/core/transaction.js.map +1 -0
  23. package/dist/dashboard/dashboard.js +6 -0
  24. package/dist/dashboard/dashboard.js.map +1 -0
  25. package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js +1072 -0
  26. package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -0
  27. package/dist/dashboard/export.js +77 -0
  28. package/dist/dashboard/export.js.map +1 -0
  29. package/dist/dashboard/filter-bar.js +6 -0
  30. package/dist/dashboard/filter-bar.js.map +1 -0
  31. package/dist/dashboard/filter-bar.vue_vue_type_script_setup_true_lang.js +150 -0
  32. package/dist/dashboard/filter-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  33. package/dist/dashboard/frame-context.js +5 -0
  34. package/dist/dashboard/frame-context.js.map +1 -0
  35. package/dist/dashboard/observers.js +48 -0
  36. package/dist/dashboard/observers.js.map +1 -0
  37. package/dist/dashboard/palette.js +6 -0
  38. package/dist/dashboard/palette.js.map +1 -0
  39. package/dist/dashboard/palette.vue_vue_type_script_setup_true_lang.js +54 -0
  40. package/dist/dashboard/palette.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/dashboard/widget-body.js +6 -0
  42. package/dist/dashboard/widget-body.js.map +1 -0
  43. package/dist/dashboard/widget-body.vue_vue_type_script_setup_true_lang.js +96 -0
  44. package/dist/dashboard/widget-body.vue_vue_type_script_setup_true_lang.js.map +1 -0
  45. package/dist/dashboard/widget-frame.js +6 -0
  46. package/dist/dashboard/widget-frame.js.map +1 -0
  47. package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js +300 -0
  48. package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js.map +1 -0
  49. package/dist/dashboard/widget-settings.js +6 -0
  50. package/dist/dashboard/widget-settings.js.map +1 -0
  51. package/dist/dashboard/widget-settings.vue_vue_type_script_setup_true_lang.js +36 -0
  52. package/dist/dashboard/widget-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  53. package/dist/data/context.js +5 -0
  54. package/dist/data/context.js.map +1 -0
  55. package/dist/data/filters.js +31 -0
  56. package/dist/data/filters.js.map +1 -0
  57. package/dist/data/store.js +214 -0
  58. package/dist/data/store.js.map +1 -0
  59. package/dist/grid/grid-handle.js +6 -0
  60. package/dist/grid/grid-handle.js.map +1 -0
  61. package/dist/grid/grid-handle.vue_vue_type_script_setup_true_lang.js +21 -0
  62. package/dist/grid/grid-handle.vue_vue_type_script_setup_true_lang.js.map +1 -0
  63. package/dist/grid/grid-item.js +80 -0
  64. package/dist/grid/grid-item.js.map +1 -0
  65. package/dist/grid/grid-layout.js +6 -0
  66. package/dist/grid/grid-layout.js.map +1 -0
  67. package/dist/grid/grid-layout.vue_vue_type_script_setup_true_lang.js +767 -0
  68. package/dist/grid/grid-layout.vue_vue_type_script_setup_true_lang.js.map +1 -0
  69. package/dist/grid/tiers.js +31 -0
  70. package/dist/grid/tiers.js.map +1 -0
  71. package/dist/index.js +23 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/layout/engine.js +284 -0
  74. package/dist/layout/engine.js.map +1 -0
  75. package/dist/layout/index.js +1 -0
  76. package/dist/locale.js +245 -0
  77. package/dist/locale.js.map +1 -0
  78. package/dist/pivot/index.js +47 -0
  79. package/dist/pivot/index.js.map +1 -0
  80. package/dist/pivot/pivot-settings.js +6 -0
  81. package/dist/pivot/pivot-settings.js.map +1 -0
  82. package/dist/pivot/pivot-settings.vue_vue_type_script_setup_true_lang.js +64 -0
  83. package/dist/pivot/pivot-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  84. package/dist/pivot/pivot.js +6 -0
  85. package/dist/pivot/pivot.js.map +1 -0
  86. package/dist/pivot/pivot.vue_vue_type_script_setup_true_lang.js +76 -0
  87. package/dist/pivot/pivot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  88. package/dist/style.css +1 -0
  89. package/dist/style.d.ts +1 -0
  90. package/dist/style.js +12 -0
  91. package/dist/types/chart/chart-settings.vue.d.ts +11 -0
  92. package/dist/types/chart/chart.vue.d.ts +3 -0
  93. package/dist/types/chart/index.d.ts +9 -0
  94. package/dist/types/chart/types.d.ts +23 -0
  95. package/dist/types/collaboration/index.d.ts +53 -0
  96. package/dist/types/collaboration/order.d.ts +20 -0
  97. package/dist/types/core/collaboration.d.ts +51 -0
  98. package/dist/types/core/document.d.ts +35 -0
  99. package/dist/types/core/history.d.ts +15 -0
  100. package/dist/types/core/transaction.d.ts +86 -0
  101. package/dist/types/core/types.d.ts +27 -0
  102. package/dist/types/dashboard/dashboard.vue.d.ts +33 -0
  103. package/dist/types/dashboard/export.d.ts +11 -0
  104. package/dist/types/dashboard/filter-bar.vue.d.ts +19 -0
  105. package/dist/types/dashboard/frame-context.d.ts +54 -0
  106. package/dist/types/dashboard/observers.d.ts +15 -0
  107. package/dist/types/dashboard/palette.vue.d.ts +20 -0
  108. package/dist/types/dashboard/types.d.ts +190 -0
  109. package/dist/types/dashboard/widget-body.vue.d.ts +19 -0
  110. package/dist/types/dashboard/widget-frame.vue.d.ts +6 -0
  111. package/dist/types/dashboard/widget-settings.vue.d.ts +16 -0
  112. package/dist/types/data/context.d.ts +18 -0
  113. package/dist/types/data/filters.d.ts +9 -0
  114. package/dist/types/data/store.d.ts +48 -0
  115. package/dist/types/data/types.d.ts +67 -0
  116. package/dist/types/grid/grid-handle.vue.d.ts +18 -0
  117. package/dist/types/grid/grid-item.d.ts +78 -0
  118. package/dist/types/grid/grid-layout.vue.d.ts +46 -0
  119. package/dist/types/grid/tiers.d.ts +12 -0
  120. package/dist/types/grid/types.d.ts +113 -0
  121. package/dist/types/index.d.ts +295 -0
  122. package/dist/types/layout/engine.d.ts +50 -0
  123. package/dist/types/layout/index.d.ts +2 -0
  124. package/dist/types/layout/types.d.ts +39 -0
  125. package/dist/types/locale.d.ts +117 -0
  126. package/dist/types/pivot/index.d.ts +14 -0
  127. package/dist/types/pivot/pivot-settings.vue.d.ts +16 -0
  128. package/dist/types/pivot/pivot.vue.d.ts +7 -0
  129. package/dist/types/pivot/types.d.ts +11 -0
  130. package/dist/types/widget/context.d.ts +91 -0
  131. package/dist/types/widget/define.d.ts +50 -0
  132. package/dist/types/widgets/field-select.vue.d.ts +18 -0
  133. package/dist/types/widgets/index.d.ts +15 -0
  134. package/dist/types/widgets/settings-field.vue.d.ts +17 -0
  135. package/dist/types/widgets/shared.d.ts +20 -0
  136. package/dist/types/widgets/source-field.vue.d.ts +15 -0
  137. package/dist/types/widgets/stat-settings.vue.d.ts +11 -0
  138. package/dist/types/widgets/stat.vue.d.ts +3 -0
  139. package/dist/types/widgets/table-settings.vue.d.ts +11 -0
  140. package/dist/types/widgets/table.vue.d.ts +3 -0
  141. package/dist/types/widgets/text-settings.vue.d.ts +11 -0
  142. package/dist/types/widgets/text.vue.d.ts +3 -0
  143. package/dist/types/widgets/types.d.ts +38 -0
  144. package/dist/widget/context.js +88 -0
  145. package/dist/widget/context.js.map +1 -0
  146. package/dist/widget/define.js +32 -0
  147. package/dist/widget/define.js.map +1 -0
  148. package/dist/widgets/field-select.js +6 -0
  149. package/dist/widgets/field-select.js.map +1 -0
  150. package/dist/widgets/field-select.vue_vue_type_script_setup_true_lang.js +54 -0
  151. package/dist/widgets/field-select.vue_vue_type_script_setup_true_lang.js.map +1 -0
  152. package/dist/widgets/index.js +74 -0
  153. package/dist/widgets/index.js.map +1 -0
  154. package/dist/widgets/settings-field.js +6 -0
  155. package/dist/widgets/settings-field.js.map +1 -0
  156. package/dist/widgets/settings-field.vue_vue_type_script_setup_true_lang.js +28 -0
  157. package/dist/widgets/settings-field.vue_vue_type_script_setup_true_lang.js.map +1 -0
  158. package/dist/widgets/shared.js +68 -0
  159. package/dist/widgets/shared.js.map +1 -0
  160. package/dist/widgets/source-field.js +6 -0
  161. package/dist/widgets/source-field.js.map +1 -0
  162. package/dist/widgets/source-field.vue_vue_type_script_setup_true_lang.js +47 -0
  163. package/dist/widgets/source-field.vue_vue_type_script_setup_true_lang.js.map +1 -0
  164. package/dist/widgets/stat-settings.js +6 -0
  165. package/dist/widgets/stat-settings.js.map +1 -0
  166. package/dist/widgets/stat-settings.vue_vue_type_script_setup_true_lang.js +107 -0
  167. package/dist/widgets/stat-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  168. package/dist/widgets/stat.js +6 -0
  169. package/dist/widgets/stat.js.map +1 -0
  170. package/dist/widgets/stat.vue_vue_type_script_setup_true_lang.js +72 -0
  171. package/dist/widgets/stat.vue_vue_type_script_setup_true_lang.js.map +1 -0
  172. package/dist/widgets/table-settings.js +6 -0
  173. package/dist/widgets/table-settings.js.map +1 -0
  174. package/dist/widgets/table-settings.vue_vue_type_script_setup_true_lang.js +90 -0
  175. package/dist/widgets/table-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  176. package/dist/widgets/table.js +6 -0
  177. package/dist/widgets/table.js.map +1 -0
  178. package/dist/widgets/table.vue_vue_type_script_setup_true_lang.js +91 -0
  179. package/dist/widgets/table.vue_vue_type_script_setup_true_lang.js.map +1 -0
  180. package/dist/widgets/text-settings.js +6 -0
  181. package/dist/widgets/text-settings.js.map +1 -0
  182. package/dist/widgets/text-settings.vue_vue_type_script_setup_true_lang.js +63 -0
  183. package/dist/widgets/text-settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  184. package/dist/widgets/text.js +6 -0
  185. package/dist/widgets/text.js.map +1 -0
  186. package/dist/widgets/text.vue_vue_type_script_setup_true_lang.js +16 -0
  187. package/dist/widgets/text.vue_vue_type_script_setup_true_lang.js.map +1 -0
  188. package/package.json +98 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 daidr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
- # Temporary Holding Version
1
+ # @dou-ui/dashboard
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [DouUI](https://github.com/daidr/dou-ui) 的仪表盘:可拖动、可缩放的网格布局,以及带数据源、筛选联动和协同编辑的仪表盘设计器。
4
+
5
+ ```sh
6
+ bun add @dou-ui/dashboard dou-ui @dou-ui/chart @dou-ui/pivot
7
+ ```
8
+
9
+ 用法见 [文档](https://ui.daidr.me/dashboard/)。
10
+
11
+ 许可证:MIT
@@ -0,0 +1,6 @@
1
+ import chart_settings_vue_vue_type_script_setup_true_lang_default from "./chart-settings.vue_vue_type_script_setup_true_lang.js";
2
+ // src/chart/chart-settings.vue
3
+ var chart_settings_default = chart_settings_vue_vue_type_script_setup_true_lang_default;
4
+ export { chart_settings_default as default };
5
+
6
+ //# sourceMappingURL=chart-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-settings.js","names":["_sfc_main"],"sources":["../../src/chart/chart-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouInput, DouSegmentedControl, DouSwitch } from 'dou-ui'\nimport { computed } from 'vue'\nimport { useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport FieldSelect from '../widgets/field-select.vue'\nimport SettingsField from '../widgets/settings-field.vue'\nimport { fieldsOf, numberFieldsOf, rowsOf } from '../widgets/shared'\nimport SourceField from '../widgets/source-field.vue'\nimport type { ChartWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardChartSettings' })\n\nconst model = defineModel<ChartWidgetProps>({ required: true })\nconst messages = useDashboardMessages()\nconst { data } = useDashboardWidget()\nconst rows = computed(() => rowsOf(data.value, model.value.path))\nconst set = (patch: Partial<ChartWidgetProps>) => (model.value = { ...model.value, ...patch })\nconst kind = computed(() => model.value.kind ?? 'line')\n</script>\n\n<template>\n <div class=\"dou-dashboard__settings\">\n <SourceField :model-value=\"model.source\" @update:model-value=\"(source) => set({ source })\" />\n <SettingsField :label=\"messages.chartKind\">\n <DouSegmentedControl\n :model-value=\"kind\"\n :options=\"[\n { value: 'line', label: messages.chartLine },\n { value: 'area', label: messages.chartArea },\n { value: 'bar', label: messages.chartBar },\n { value: 'pie', label: messages.chartPie },\n ]\"\n :aria-label=\"messages.chartKind\"\n @update:model-value=\"(value) => set({ kind: value as ChartWidgetProps['kind'] })\"\n />\n </SettingsField>\n <FieldSelect\n :model-value=\"model.x\"\n :label=\"messages.xField\"\n :fields=\"fieldsOf(rows)\"\n @update:model-value=\"(x) => set({ x: x as string | undefined })\"\n />\n <FieldSelect\n :model-value=\"kind === 'pie' ? (model.y ?? []).slice(0, 1) : model.y\"\n :label=\"messages.yFields\"\n :fields=\"numberFieldsOf(rows)\"\n :multiple=\"kind !== 'pie'\"\n @update:model-value=\"\n (y) => set({ y: y === undefined ? undefined : Array.isArray(y) ? y : [y] })\n \"\n />\n <div v-if=\"kind === 'bar' || kind === 'area'\" class=\"dou-dashboard__field-row\">\n <DouSwitch\n :model-value=\"!!model.stacked\"\n @update:model-value=\"(stacked) => set({ stacked: stacked || undefined })\"\n >\n {{ messages.stacked }}\n </DouSwitch>\n <DouSwitch\n v-if=\"kind === 'bar'\"\n :model-value=\"!!model.horizontal\"\n @update:model-value=\"(horizontal) => set({ horizontal: horizontal || undefined })\"\n >\n {{ messages.horizontal }}\n </DouSwitch>\n </div>\n <SettingsField :label=\"messages.chartFilter\" :hint=\"messages.chartFilterHint\">\n <DouInput\n :model-value=\"model.filter ?? ''\"\n :aria-label=\"messages.chartFilter\"\n @update:model-value=\"(key) => set({ filter: key.trim() || undefined })\"\n />\n </SettingsField>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,122 @@
1
+ import { useDashboardMessages } from "../locale.js";
2
+ import { useDashboardWidget } from "../widget/context.js";
3
+ import { fieldsOf, numberFieldsOf, rowsOf } from "../widgets/shared.js";
4
+ import settings_field_default from "../widgets/settings-field.js";
5
+ import field_select_default from "../widgets/field-select.js";
6
+ import source_field_default from "../widgets/source-field.js";
7
+ import { DouInput, DouSegmentedControl, DouSwitch } from "dou-ui";
8
+ import { computed, createBlock, createCommentVNode, createElementBlock, createTextVNode, createVNode, defineComponent, openBlock, toDisplayString, unref, useModel, withCtx } from "vue";
9
+ // src/chart/chart-settings.vue?vue&type=script&setup=true&lang.ts
10
+ var _hoisted_1 = { class: "dou-dashboard__settings" };
11
+ var _hoisted_2 = {
12
+ key: 0,
13
+ class: "dou-dashboard__field-row"
14
+ };
15
+ var chart_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
16
+ name: "DouDashboardChartSettings",
17
+ __name: "chart-settings",
18
+ props: {
19
+ "modelValue": { required: true },
20
+ "modelModifiers": {}
21
+ },
22
+ emits: ["update:modelValue"],
23
+ setup(__props) {
24
+ const model = useModel(__props, "modelValue");
25
+ const messages = useDashboardMessages();
26
+ const { data } = useDashboardWidget();
27
+ const rows = computed(() => rowsOf(data.value, model.value.path));
28
+ const set = (patch) => model.value = {
29
+ ...model.value,
30
+ ...patch
31
+ };
32
+ const kind = computed(() => model.value.kind ?? "line");
33
+ return (_ctx, _cache) => {
34
+ return openBlock(), createElementBlock("div", _hoisted_1, [
35
+ createVNode(source_field_default, {
36
+ "model-value": model.value.source,
37
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = (source) => set({ source }))
38
+ }, null, 8, ["model-value"]),
39
+ createVNode(settings_field_default, { label: unref(messages).chartKind }, {
40
+ default: withCtx(() => [createVNode(unref(DouSegmentedControl), {
41
+ "model-value": kind.value,
42
+ options: [
43
+ {
44
+ value: "line",
45
+ label: unref(messages).chartLine
46
+ },
47
+ {
48
+ value: "area",
49
+ label: unref(messages).chartArea
50
+ },
51
+ {
52
+ value: "bar",
53
+ label: unref(messages).chartBar
54
+ },
55
+ {
56
+ value: "pie",
57
+ label: unref(messages).chartPie
58
+ }
59
+ ],
60
+ "aria-label": unref(messages).chartKind,
61
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = (value) => set({ kind: value }))
62
+ }, null, 8, [
63
+ "model-value",
64
+ "options",
65
+ "aria-label"
66
+ ])]),
67
+ _: 1
68
+ }, 8, ["label"]),
69
+ createVNode(field_select_default, {
70
+ "model-value": model.value.x,
71
+ label: unref(messages).xField,
72
+ fields: unref(fieldsOf)(rows.value),
73
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = (x) => set({ x }))
74
+ }, null, 8, [
75
+ "model-value",
76
+ "label",
77
+ "fields"
78
+ ]),
79
+ createVNode(field_select_default, {
80
+ "model-value": kind.value === "pie" ? (model.value.y ?? []).slice(0, 1) : model.value.y,
81
+ label: unref(messages).yFields,
82
+ fields: unref(numberFieldsOf)(rows.value),
83
+ multiple: kind.value !== "pie",
84
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = (y) => set({ y: y === void 0 ? void 0 : Array.isArray(y) ? y : [y] }))
85
+ }, null, 8, [
86
+ "model-value",
87
+ "label",
88
+ "fields",
89
+ "multiple"
90
+ ]),
91
+ kind.value === "bar" || kind.value === "area" ? (openBlock(), createElementBlock("div", _hoisted_2, [createVNode(unref(DouSwitch), {
92
+ "model-value": !!model.value.stacked,
93
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = (stacked) => set({ stacked: stacked || void 0 }))
94
+ }, {
95
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(messages).stacked), 1)]),
96
+ _: 1
97
+ }, 8, ["model-value"]), kind.value === "bar" ? (openBlock(), createBlock(unref(DouSwitch), {
98
+ key: 0,
99
+ "model-value": !!model.value.horizontal,
100
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = (horizontal) => set({ horizontal: horizontal || void 0 }))
101
+ }, {
102
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(messages).horizontal), 1)]),
103
+ _: 1
104
+ }, 8, ["model-value"])) : createCommentVNode("", true)])) : createCommentVNode("", true),
105
+ createVNode(settings_field_default, {
106
+ label: unref(messages).chartFilter,
107
+ hint: unref(messages).chartFilterHint
108
+ }, {
109
+ default: withCtx(() => [createVNode(unref(DouInput), {
110
+ "model-value": model.value.filter ?? "",
111
+ "aria-label": unref(messages).chartFilter,
112
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = (key) => set({ filter: key.trim() || void 0 }))
113
+ }, null, 8, ["model-value", "aria-label"])]),
114
+ _: 1
115
+ }, 8, ["label", "hint"])
116
+ ]);
117
+ };
118
+ }
119
+ });
120
+ export { chart_settings_vue_vue_type_script_setup_true_lang_default as default };
121
+
122
+ //# sourceMappingURL=chart-settings.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-settings.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createVNode","SourceField","SettingsField","_unref","_withCtx","FieldSelect","_createTextVNode","_toDisplayString","_createBlock","_createCommentVNode"],"sources":["../../src/chart/chart-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouInput, DouSegmentedControl, DouSwitch } from 'dou-ui'\nimport { computed } from 'vue'\nimport { useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport FieldSelect from '../widgets/field-select.vue'\nimport SettingsField from '../widgets/settings-field.vue'\nimport { fieldsOf, numberFieldsOf, rowsOf } from '../widgets/shared'\nimport SourceField from '../widgets/source-field.vue'\nimport type { ChartWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardChartSettings' })\n\nconst model = defineModel<ChartWidgetProps>({ required: true })\nconst messages = useDashboardMessages()\nconst { data } = useDashboardWidget()\nconst rows = computed(() => rowsOf(data.value, model.value.path))\nconst set = (patch: Partial<ChartWidgetProps>) => (model.value = { ...model.value, ...patch })\nconst kind = computed(() => model.value.kind ?? 'line')\n</script>\n\n<template>\n <div class=\"dou-dashboard__settings\">\n <SourceField :model-value=\"model.source\" @update:model-value=\"(source) => set({ source })\" />\n <SettingsField :label=\"messages.chartKind\">\n <DouSegmentedControl\n :model-value=\"kind\"\n :options=\"[\n { value: 'line', label: messages.chartLine },\n { value: 'area', label: messages.chartArea },\n { value: 'bar', label: messages.chartBar },\n { value: 'pie', label: messages.chartPie },\n ]\"\n :aria-label=\"messages.chartKind\"\n @update:model-value=\"(value) => set({ kind: value as ChartWidgetProps['kind'] })\"\n />\n </SettingsField>\n <FieldSelect\n :model-value=\"model.x\"\n :label=\"messages.xField\"\n :fields=\"fieldsOf(rows)\"\n @update:model-value=\"(x) => set({ x: x as string | undefined })\"\n />\n <FieldSelect\n :model-value=\"kind === 'pie' ? (model.y ?? []).slice(0, 1) : model.y\"\n :label=\"messages.yFields\"\n :fields=\"numberFieldsOf(rows)\"\n :multiple=\"kind !== 'pie'\"\n @update:model-value=\"\n (y) => set({ y: y === undefined ? undefined : Array.isArray(y) ? y : [y] })\n \"\n />\n <div v-if=\"kind === 'bar' || kind === 'area'\" class=\"dou-dashboard__field-row\">\n <DouSwitch\n :model-value=\"!!model.stacked\"\n @update:model-value=\"(stacked) => set({ stacked: stacked || undefined })\"\n >\n {{ messages.stacked }}\n </DouSwitch>\n <DouSwitch\n v-if=\"kind === 'bar'\"\n :model-value=\"!!model.horizontal\"\n @update:model-value=\"(horizontal) => set({ horizontal: horizontal || undefined })\"\n >\n {{ messages.horizontal }}\n </DouSwitch>\n </div>\n <SettingsField :label=\"messages.chartFilter\" :hint=\"messages.chartFilterHint\">\n <DouInput\n :model-value=\"model.filter ?? ''\"\n :aria-label=\"messages.chartFilter\"\n @update:model-value=\"(key) => set({ filter: key.trim() || undefined })\"\n />\n </SettingsField>\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import chart_vue_vue_type_script_setup_true_lang_default from "./chart.vue_vue_type_script_setup_true_lang.js";
2
+ // src/chart/chart.vue
3
+ var chart_default = chart_vue_vue_type_script_setup_true_lang_default;
4
+ export { chart_default as default };
5
+
6
+ //# sourceMappingURL=chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.js","names":["_sfc_main"],"sources":["../../src/chart/chart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n DouChart,\n DouChartArea,\n DouChartBar,\n DouChartLine,\n DouChartPie,\n DouChartTooltip,\n} from '@dou-ui/chart'\nimport type { ChartPointEvent } from '@dou-ui/chart'\nimport { computed, watch } from 'vue'\nimport { useDashboardWidget } from '../widget/context'\nimport { filterValueOf, rowsOf, rowsToWorkbook } from '../widgets/shared'\nimport type { ChartWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardChartWidget' })\n\nconst { props, data, size, setFilter, ownFilters, widget, setWorkbook } =\n useDashboardWidget<ChartWidgetProps>()\nconst rows = computed(() => rowsOf(data.value, props.value.path))\nconst kind = computed(() => props.value.kind ?? 'line')\nconst ys = computed(() => props.value.y ?? [])\nconst nameOf = (key: string) => props.value.labels?.[key] ?? key\n/** The x this widget filters by, if any: the other bars fade. */\nconst picked = computed(() =>\n props.value.filter ? ownFilters.value[props.value.filter] : undefined,\n)\n/** Bars other than the picked one turn gray; a new function when the pick changes, so they draw again. */\nconst barColor = computed(() => {\n const value = picked.value\n const x = props.value.x ?? ''\n if (!props.value.filter || value === undefined) return undefined\n return (row: Record<string, unknown>) =>\n filterValueOf(row[x]) === value ? undefined : 'var(--dou-color-border-strong)'\n})\n\n// the export menu writes the chart's data: a column for x, one for each series;\n// a chart without its fields has no menu\nconst seriesKeys = computed(() => (kind.value === 'pie' ? ys.value.slice(0, 1) : ys.value))\nconst exportable = computed(() => !!props.value.x && seriesKeys.value.length > 0)\nwatch(\n exportable,\n (ok) =>\n setWorkbook(\n ok\n ? () => {\n const x = props.value.x!\n return rowsToWorkbook(\n '',\n [\n { key: x, title: nameOf(x) },\n ...seriesKeys.value.map((key) => ({ key, title: nameOf(key) })),\n ],\n rows.value,\n )\n }\n : null,\n ),\n { immediate: true },\n)\n\nfunction onSelect(event: ChartPointEvent) {\n const key = props.value.filter\n if (!key) return\n const value = filterValueOf(event.x)\n if (value === picked.value) setFilter(key, undefined)\n else setFilter(key, value, { label: event.title ?? String(value) })\n}\n</script>\n\n<template>\n <DouChart\n class=\"dou-dashboard-chart\"\n :data=\"rows\"\n :x=\"props.x\"\n :height=\"size.height.value || 160\"\n :horizontal=\"kind === 'bar' && props.horizontal\"\n :legend=\"kind === 'pie' || ys.length > 1\"\n :aria-label=\"widget.title\"\n v-on=\"props.filter ? { select: onSelect } : {}\"\n >\n <DouChartPie\n v-if=\"kind === 'pie'\"\n :value=\"ys[0] ?? ''\"\n :name=\"ys[0] ? nameOf(ys[0]) : undefined\"\n :inner-radius=\"0.6\"\n />\n <template v-else>\n <template v-for=\"y in ys\" :key=\"y\">\n <DouChartBar\n v-if=\"kind === 'bar'\"\n :y=\"y\"\n :name=\"nameOf(y)\"\n :stack=\"props.stacked || undefined\"\n :color=\"barColor\"\n />\n <DouChartArea\n v-else-if=\"kind === 'area'\"\n :y=\"y\"\n :name=\"nameOf(y)\"\n :stack=\"props.stacked || undefined\"\n />\n <DouChartLine v-else :y=\"y\" :name=\"nameOf(y)\" />\n </template>\n </template>\n <DouChartTooltip />\n </DouChart>\n</template>\n"],"mappings":""}
@@ -0,0 +1,99 @@
1
+ import { useDashboardWidget } from "../widget/context.js";
2
+ import { filterValueOf, rowsOf, rowsToWorkbook } from "../widgets/shared.js";
3
+ import { Fragment, computed, createBlock, createElementBlock, createVNode, defineComponent, mergeProps, openBlock, renderList, toHandlers, unref, watch, withCtx } from "vue";
4
+ import { DouChart, DouChartArea, DouChartBar, DouChartLine, DouChartPie, DouChartTooltip } from "@dou-ui/chart";
5
+ // src/chart/chart.vue?vue&type=script&setup=true&lang.ts
6
+ var chart_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
+ name: "DouDashboardChartWidget",
8
+ __name: "chart",
9
+ setup(__props) {
10
+ const { props, data, size, setFilter, ownFilters, widget, setWorkbook } = useDashboardWidget();
11
+ const rows = computed(() => rowsOf(data.value, props.value.path));
12
+ const kind = computed(() => props.value.kind ?? "line");
13
+ const ys = computed(() => props.value.y ?? []);
14
+ const nameOf = (key) => props.value.labels?.[key] ?? key;
15
+ /** The x this widget filters by, if any: the other bars fade. */
16
+ const picked = computed(() => props.value.filter ? ownFilters.value[props.value.filter] : void 0);
17
+ /** Bars other than the picked one turn gray; a new function when the pick changes, so they draw again. */
18
+ const barColor = computed(() => {
19
+ const value = picked.value;
20
+ const x = props.value.x ?? "";
21
+ if (!props.value.filter || value === void 0) return void 0;
22
+ return (row) => filterValueOf(row[x]) === value ? void 0 : "var(--dou-color-border-strong)";
23
+ });
24
+ const seriesKeys = computed(() => kind.value === "pie" ? ys.value.slice(0, 1) : ys.value);
25
+ const exportable = computed(() => !!props.value.x && seriesKeys.value.length > 0);
26
+ watch(exportable, (ok) => setWorkbook(ok ? () => {
27
+ const x = props.value.x;
28
+ return rowsToWorkbook("", [{
29
+ key: x,
30
+ title: nameOf(x)
31
+ }, ...seriesKeys.value.map((key) => ({
32
+ key,
33
+ title: nameOf(key)
34
+ }))], rows.value);
35
+ } : null), { immediate: true });
36
+ function onSelect(event) {
37
+ const key = props.value.filter;
38
+ if (!key) return;
39
+ const value = filterValueOf(event.x);
40
+ if (value === picked.value) setFilter(key, void 0);
41
+ else setFilter(key, value, { label: event.title ?? String(value) });
42
+ }
43
+ return (_ctx, _cache) => {
44
+ return openBlock(), createBlock(unref(DouChart), mergeProps({
45
+ class: "dou-dashboard-chart",
46
+ data: rows.value,
47
+ x: unref(props).x,
48
+ height: unref(size).height.value || 160,
49
+ horizontal: kind.value === "bar" && unref(props).horizontal,
50
+ legend: kind.value === "pie" || ys.value.length > 1,
51
+ "aria-label": unref(widget).title
52
+ }, toHandlers(unref(props).filter ? { select: onSelect } : {})), {
53
+ default: withCtx(() => [kind.value === "pie" ? (openBlock(), createBlock(unref(DouChartPie), {
54
+ key: 0,
55
+ value: ys.value[0] ?? "",
56
+ name: ys.value[0] ? nameOf(ys.value[0]) : void 0,
57
+ "inner-radius": .6
58
+ }, null, 8, ["value", "name"])) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(ys.value, (y) => {
59
+ return openBlock(), createElementBlock(Fragment, { key: y }, [kind.value === "bar" ? (openBlock(), createBlock(unref(DouChartBar), {
60
+ key: 0,
61
+ y,
62
+ name: nameOf(y),
63
+ stack: unref(props).stacked || void 0,
64
+ color: barColor.value
65
+ }, null, 8, [
66
+ "y",
67
+ "name",
68
+ "stack",
69
+ "color"
70
+ ])) : kind.value === "area" ? (openBlock(), createBlock(unref(DouChartArea), {
71
+ key: 1,
72
+ y,
73
+ name: nameOf(y),
74
+ stack: unref(props).stacked || void 0
75
+ }, null, 8, [
76
+ "y",
77
+ "name",
78
+ "stack"
79
+ ])) : (openBlock(), createBlock(unref(DouChartLine), {
80
+ key: 2,
81
+ y,
82
+ name: nameOf(y)
83
+ }, null, 8, ["y", "name"]))], 64);
84
+ }), 128)), createVNode(unref(DouChartTooltip))]),
85
+ _: 1
86
+ }, 16, [
87
+ "data",
88
+ "x",
89
+ "height",
90
+ "horizontal",
91
+ "legend",
92
+ "aria-label"
93
+ ]);
94
+ };
95
+ }
96
+ });
97
+ export { chart_vue_vue_type_script_setup_true_lang_default as default };
98
+
99
+ //# sourceMappingURL=chart.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_mergeProps","_toHandlers","_withCtx","_createElementBlock","_Fragment","_renderList","_createVNode"],"sources":["../../src/chart/chart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n DouChart,\n DouChartArea,\n DouChartBar,\n DouChartLine,\n DouChartPie,\n DouChartTooltip,\n} from '@dou-ui/chart'\nimport type { ChartPointEvent } from '@dou-ui/chart'\nimport { computed, watch } from 'vue'\nimport { useDashboardWidget } from '../widget/context'\nimport { filterValueOf, rowsOf, rowsToWorkbook } from '../widgets/shared'\nimport type { ChartWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardChartWidget' })\n\nconst { props, data, size, setFilter, ownFilters, widget, setWorkbook } =\n useDashboardWidget<ChartWidgetProps>()\nconst rows = computed(() => rowsOf(data.value, props.value.path))\nconst kind = computed(() => props.value.kind ?? 'line')\nconst ys = computed(() => props.value.y ?? [])\nconst nameOf = (key: string) => props.value.labels?.[key] ?? key\n/** The x this widget filters by, if any: the other bars fade. */\nconst picked = computed(() =>\n props.value.filter ? ownFilters.value[props.value.filter] : undefined,\n)\n/** Bars other than the picked one turn gray; a new function when the pick changes, so they draw again. */\nconst barColor = computed(() => {\n const value = picked.value\n const x = props.value.x ?? ''\n if (!props.value.filter || value === undefined) return undefined\n return (row: Record<string, unknown>) =>\n filterValueOf(row[x]) === value ? undefined : 'var(--dou-color-border-strong)'\n})\n\n// the export menu writes the chart's data: a column for x, one for each series;\n// a chart without its fields has no menu\nconst seriesKeys = computed(() => (kind.value === 'pie' ? ys.value.slice(0, 1) : ys.value))\nconst exportable = computed(() => !!props.value.x && seriesKeys.value.length > 0)\nwatch(\n exportable,\n (ok) =>\n setWorkbook(\n ok\n ? () => {\n const x = props.value.x!\n return rowsToWorkbook(\n '',\n [\n { key: x, title: nameOf(x) },\n ...seriesKeys.value.map((key) => ({ key, title: nameOf(key) })),\n ],\n rows.value,\n )\n }\n : null,\n ),\n { immediate: true },\n)\n\nfunction onSelect(event: ChartPointEvent) {\n const key = props.value.filter\n if (!key) return\n const value = filterValueOf(event.x)\n if (value === picked.value) setFilter(key, undefined)\n else setFilter(key, value, { label: event.title ?? String(value) })\n}\n</script>\n\n<template>\n <DouChart\n class=\"dou-dashboard-chart\"\n :data=\"rows\"\n :x=\"props.x\"\n :height=\"size.height.value || 160\"\n :horizontal=\"kind === 'bar' && props.horizontal\"\n :legend=\"kind === 'pie' || ys.length > 1\"\n :aria-label=\"widget.title\"\n v-on=\"props.filter ? { select: onSelect } : {}\"\n >\n <DouChartPie\n v-if=\"kind === 'pie'\"\n :value=\"ys[0] ?? ''\"\n :name=\"ys[0] ? nameOf(ys[0]) : undefined\"\n :inner-radius=\"0.6\"\n />\n <template v-else>\n <template v-for=\"y in ys\" :key=\"y\">\n <DouChartBar\n v-if=\"kind === 'bar'\"\n :y=\"y\"\n :name=\"nameOf(y)\"\n :stack=\"props.stacked || undefined\"\n :color=\"barColor\"\n />\n <DouChartArea\n v-else-if=\"kind === 'area'\"\n :y=\"y\"\n :name=\"nameOf(y)\"\n :stack=\"props.stacked || undefined\"\n />\n <DouChartLine v-else :y=\"y\" :name=\"nameOf(y)\" />\n </template>\n </template>\n <DouChartTooltip />\n </DouChart>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { defineDashboardWidget } from "../widget/define.js";
2
+ import chart_default from "./chart.js";
3
+ import chart_settings_default from "./chart-settings.js";
4
+ import { BarChartIcon } from "@dou-ui/icons";
5
+ // src/chart/index.ts
6
+ /**
7
+ * A chart of a source's rows (line, area, bar or pie), drawn with
8
+ * `@dou-ui/chart`; clicking an x can filter the other widgets. Needs
9
+ * `@dou-ui/chart` and its styles.
10
+ */
11
+ function chartWidget(overrides = {}) {
12
+ return defineDashboardWidget({
13
+ type: "chart",
14
+ label: "图表",
15
+ icon: BarChartIcon,
16
+ size: {
17
+ w: 6,
18
+ h: 4,
19
+ minW: 3,
20
+ minH: 3
21
+ },
22
+ defaultProps: {
23
+ kind: "line",
24
+ y: []
25
+ },
26
+ component: chart_default,
27
+ settings: chart_settings_default,
28
+ ...overrides
29
+ });
30
+ }
31
+ export { chartWidget };
32
+
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Chart","ChartSettings"],"sources":["../../src/chart/index.ts"],"sourcesContent":["import { BarChartIcon } from '@dou-ui/icons'\nimport { defineDashboardWidget } from '../widget/define'\nimport type { WidgetOverrides } from '../widgets'\nimport Chart from './chart.vue'\nimport ChartSettings from './chart-settings.vue'\nimport type { ChartWidgetProps } from './types'\n\nexport type { ChartWidgetProps } from './types'\n\n/**\n * A chart of a source's rows (line, area, bar or pie), drawn with\n * `@dou-ui/chart`; clicking an x can filter the other widgets. Needs\n * `@dou-ui/chart` and its styles.\n */\nexport function chartWidget(overrides: WidgetOverrides<ChartWidgetProps> = {}) {\n return defineDashboardWidget<ChartWidgetProps>({\n type: 'chart',\n label: '图表',\n icon: BarChartIcon,\n size: { w: 6, h: 4, minW: 3, minH: 3 },\n defaultProps: { kind: 'line', y: [] },\n component: Chart,\n settings: ChartSettings,\n ...overrides,\n })\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAgB,YAAY,YAA+C,CAAC,GAAG;CAC7E,OAAO,sBAAwC;EAC7C,MAAM;EACN,OAAO;EACP,MAAM;EACN,MAAM;GAAE,GAAG;GAAG,GAAG;GAAG,MAAM;GAAG,MAAM;EAAE;EACrC,cAAc;GAAE,MAAM;GAAQ,GAAG,CAAC;EAAE;EACpC,WAAWA;EACX,UAAUC;EACV,GAAG;CACL,CAAC;AACH"}
@@ -0,0 +1,281 @@
1
+ import { orderKeys } from "./order.js";
2
+ import { collaborationColors } from "dou-ui";
3
+ import { shallowRef } from "vue";
4
+ import * as Y from "yjs";
5
+ // src/collaboration/index.ts
6
+ /** A widget's place among the others, kept beside its keys. */
7
+ var ORDER = "$order";
8
+ /** The places by breakpoint, a map of their own, so places on two breakpoints don't overwrite each other. */
9
+ var PLACE = "place";
10
+ var same = (a, b) => a === b || typeof a === "object" && typeof b === "object" && JSON.stringify(a) === JSON.stringify(b);
11
+ /** Where in `value` something JSON can't carry sits, e.g. a component or a function. */
12
+ function unshareable(value, path) {
13
+ if (value === null || [
14
+ "string",
15
+ "number",
16
+ "boolean",
17
+ "undefined"
18
+ ].includes(typeof value)) return null;
19
+ if (typeof value !== "object") return path;
20
+ const proto = Object.getPrototypeOf(value);
21
+ if (!Array.isArray(value) && proto !== Object.prototype && proto !== null) return path;
22
+ for (const [key, item] of Object.entries(value)) {
23
+ const found = unshareable(item, Array.isArray(value) ? `${path}[${key}]` : `${path}.${key}`);
24
+ if (found) return found;
25
+ }
26
+ return null;
27
+ }
28
+ var warned = /* @__PURE__ */ new Set();
29
+ /** Others would get a broken copy of such a value while this dashboard shows it fine. */
30
+ function warnUnshareable(id, key, value) {
31
+ if (process.env.NODE_ENV === "production") return;
32
+ const path = unshareable(value, key);
33
+ if (!path || warned.has(`${id}:${path}`)) return;
34
+ warned.add(`${id}:${path}`);
35
+ console.warn(`[@dou-ui/dashboard] "${id}" has ${path}, which can't be shared: only JSON values reach the others.`);
36
+ }
37
+ /** Writes the places that changed into a widget's place map. */
38
+ function writePlace(fields, place) {
39
+ const shared = fields.get(PLACE);
40
+ if (!(shared instanceof Y.Map)) {
41
+ const map = new Y.Map();
42
+ for (const [name, value] of Object.entries(place)) if (value) map.set(name, { ...value });
43
+ fields.set(PLACE, map);
44
+ return;
45
+ }
46
+ for (const [name, value] of Object.entries(place)) if (value && !same(shared.get(name), value)) shared.set(name, { ...value });
47
+ for (const name of Array.from(shared.keys())) if (!place[name]) shared.delete(name);
48
+ }
49
+ /** Writes a widget's keys besides its order, only those that changed; `keys` limits which. */
50
+ function writeWidget(map, widget, keys) {
51
+ const existing = map.get(widget.id);
52
+ const item = widget;
53
+ if (!(existing instanceof Y.Map)) {
54
+ const fields = new Y.Map();
55
+ for (const [key, value] of Object.entries(item)) {
56
+ if (key === "id" || value === void 0) continue;
57
+ if (key === PLACE) {
58
+ const places = new Y.Map();
59
+ for (const [name, place] of Object.entries(value)) if (place) places.set(name, { ...place });
60
+ fields.set(PLACE, places);
61
+ continue;
62
+ }
63
+ warnUnshareable(widget.id, key, value);
64
+ fields.set(key, value);
65
+ }
66
+ map.set(widget.id, fields);
67
+ return;
68
+ }
69
+ for (const [key, value] of Object.entries(item)) {
70
+ if (key === "id" || value === void 0 || keys && !keys.has(key)) continue;
71
+ if (key === PLACE) writePlace(existing, value);
72
+ else if (!same(existing.get(key), value)) {
73
+ warnUnshareable(widget.id, key, value);
74
+ existing.set(key, value);
75
+ }
76
+ }
77
+ for (const key of Array.from(existing.keys())) if (key[0] !== "$" && item[key] === void 0 && (!keys || keys.has(key))) existing.delete(key);
78
+ }
79
+ /** Writes each widget's order key, giving new keys only where it must. */
80
+ function writeOrder(map, widgets) {
81
+ const shared = widgets.map((widget) => {
82
+ const fields = map.get(widget.id);
83
+ return fields instanceof Y.Map ? fields : null;
84
+ });
85
+ const keys = orderKeys(shared.map((fields) => fields?.get(ORDER) ?? null));
86
+ shared.forEach((fields, index) => {
87
+ if (fields && fields.get(ORDER) !== keys[index]) fields.set(ORDER, keys[index]);
88
+ });
89
+ }
90
+ /**
91
+ * Writes a dashboard into an empty map, e.g. when a dashboard so far saved
92
+ * as JSON starts being edited together. Do it once, where the shared
93
+ * document is created; otherwise the first person to open the dashboard
94
+ * brings theirs.
95
+ */
96
+ function fillMap(map, document) {
97
+ const fill = () => {
98
+ for (const widget of document.widgets) writeWidget(map, widget);
99
+ writeOrder(map, document.widgets);
100
+ };
101
+ if (map.doc) map.doc.transact(fill);
102
+ else fill();
103
+ }
104
+ /** The dashboard the map holds: its widgets by their order keys (then ids, the same for everyone). */
105
+ function readMap(map) {
106
+ const list = [];
107
+ map.forEach((value, id) => {
108
+ if (!(value instanceof Y.Map)) return;
109
+ const { [ORDER]: order, ...rest } = value.toJSON();
110
+ if (typeof rest.type !== "string") return;
111
+ const place = rest[PLACE];
112
+ list.push({
113
+ widget: {
114
+ ...rest,
115
+ id,
116
+ place: place && typeof place === "object" ? place : {}
117
+ },
118
+ order: typeof order === "string" ? order : ""
119
+ });
120
+ });
121
+ list.sort((a, b) => a.order < b.order ? -1 : a.order > b.order ? 1 : a.widget.id < b.widget.id ? -1 : 1);
122
+ return {
123
+ version: 1,
124
+ widgets: list.map((entry) => entry.widget)
125
+ };
126
+ }
127
+ /** The widgets and keys a transaction changed, written to the map. */
128
+ function writeChanges(map, tr) {
129
+ const after = new Map(tr.doc.widgets.map((widget) => [widget.id, widget]));
130
+ const touched = /* @__PURE__ */ new Map();
131
+ let added = false;
132
+ let removed = false;
133
+ for (const step of tr.steps) if (step.type === "add") {
134
+ touched.set(step.widget.id, true);
135
+ added = true;
136
+ } else if (step.type === "remove") {
137
+ removed = true;
138
+ touched.delete(step.id);
139
+ } else {
140
+ const current = touched.get(step.id);
141
+ if (current === true) continue;
142
+ const keys = current ?? /* @__PURE__ */ new Set();
143
+ for (const key of Object.keys(step.patch)) keys.add(key);
144
+ touched.set(step.id, keys);
145
+ }
146
+ if (removed) {
147
+ for (const widget of tr.before.widgets) if (!after.has(widget.id)) map.delete(widget.id);
148
+ }
149
+ for (const [id, keys] of touched) {
150
+ const widget = after.get(id);
151
+ if (!widget) continue;
152
+ if (keys === true && map.get(id) instanceof Y.Map && removed) map.delete(id);
153
+ writeWidget(map, widget, keys === true ? void 0 : keys);
154
+ }
155
+ if (added) writeOrder(map, tr.doc.widgets);
156
+ }
157
+ var NO_PEERS = [];
158
+ /**
159
+ * Edit a dashboard together through a Yjs document: pass the result to
160
+ * `DouDashboard` as `collaboration`. Each widget lives in `widgets` as its
161
+ * own `Y.Map`, each key on its own and each breakpoint's place on its own,
162
+ * so two people changing different widgets, or different settings of one,
163
+ * both keep their change. When two people move widgets at once, everyone
164
+ * lays the places out the same way, so the dashboards agree. While a widget
165
+ * is dragged, changes from others wait until it is let go. The dashboard's
166
+ * `v-model` only mirrors the shared document: a document set through
167
+ * `v-model` from outside is not written back. Undo only takes back this
168
+ * user's own changes. With `awareness`, each person sees which widget the
169
+ * others are at, outlined in their colors, and whether they are moving,
170
+ * resizing or changing its settings.
171
+ */
172
+ function collaboration(options) {
173
+ const { widgets: map, awareness, user } = options;
174
+ const ydoc = map.doc;
175
+ if (!ydoc) throw new Error("[@dou-ui/dashboard] widgets must be a map of a Y.Doc");
176
+ if (awareness && user) {
177
+ const color = user.color ?? collaborationColors[ydoc.clientID % collaborationColors.length];
178
+ awareness.setLocalStateField("user", {
179
+ name: user.name,
180
+ color
181
+ });
182
+ }
183
+ /** This dashboard's own changes, which undo can take back. */
184
+ const tracked = { dashboard: "tracked" };
185
+ /** Changes undo leaves alone, e.g. filling the map. */
186
+ const untracked = { dashboard: "untracked" };
187
+ const undoManager = new Y.UndoManager([map], {
188
+ trackedOrigins: /* @__PURE__ */ new Set([tracked]),
189
+ captureTimeout: 500
190
+ });
191
+ /** Bumped when the undo stacks change, so `canUndo` and `canRedo` update. */
192
+ const stacks = shallowRef(0);
193
+ const bump = () => stacks.value++;
194
+ undoManager.on("stack-item-added", bump);
195
+ undoManager.on("stack-item-popped", bump);
196
+ undoManager.on("stack-cleared", bump);
197
+ let host;
198
+ /** What undo or redo is running, to name the change. */
199
+ let travelling = null;
200
+ let lastGroup;
201
+ /** Brings the dashboard in line with the map. */
202
+ function pull() {
203
+ host?.apply(readMap(map), travelling ?? "remote");
204
+ }
205
+ function run(action) {
206
+ if (!(action === "undo" ? undoManager.undoStack : undoManager.redoStack).length) return false;
207
+ travelling = action;
208
+ try {
209
+ undoManager[action]();
210
+ } finally {
211
+ travelling = null;
212
+ }
213
+ return true;
214
+ }
215
+ /** The others at each widget. */
216
+ const peersByWidget = shallowRef(/* @__PURE__ */ new Map());
217
+ function readPeers() {
218
+ if (!awareness) return;
219
+ const next = /* @__PURE__ */ new Map();
220
+ awareness.getStates().forEach((state, client) => {
221
+ if (client === awareness.clientID) return;
222
+ const who = state.user;
223
+ const presence = state.dashboard;
224
+ if (!who || !presence?.widget) return;
225
+ const peer = {
226
+ client,
227
+ name: who.name ?? "",
228
+ color: who.color ?? "currentColor",
229
+ action: presence.action
230
+ };
231
+ const list = next.get(presence.widget);
232
+ if (list) list.push(peer);
233
+ else next.set(presence.widget, [peer]);
234
+ });
235
+ peersByWidget.value = next;
236
+ }
237
+ return {
238
+ setup(dashboard) {
239
+ host = dashboard;
240
+ if (!map.size) ydoc.transact(() => fillMap(map, dashboard.document()), untracked);
241
+ pull();
242
+ let dirty = false;
243
+ const observe = (_events, transaction) => {
244
+ if (transaction.origin !== tracked && transaction.origin !== untracked) dirty = true;
245
+ };
246
+ const flush = () => {
247
+ if (!dirty) return;
248
+ dirty = false;
249
+ pull();
250
+ };
251
+ map.observeDeep(observe);
252
+ ydoc.on("afterTransaction", flush);
253
+ if (awareness) {
254
+ readPeers();
255
+ awareness.on("change", readPeers);
256
+ }
257
+ return () => {
258
+ map.unobserveDeep(observe);
259
+ ydoc.off("afterTransaction", flush);
260
+ if (awareness) awareness.off("change", readPeers);
261
+ host = void 0;
262
+ };
263
+ },
264
+ transaction(tr) {
265
+ const tracking = tr.meta.history !== false;
266
+ if (tracking && (!tr.meta.group || tr.meta.group !== lastGroup)) undoManager.stopCapturing();
267
+ if (tracking) lastGroup = tr.meta.group;
268
+ ydoc.transact(() => writeChanges(map, tr), tracking ? tracked : untracked);
269
+ },
270
+ sync: pull,
271
+ undo: () => run("undo"),
272
+ redo: () => run("redo"),
273
+ canUndo: () => (stacks.value, undoManager.undoStack.length > 0),
274
+ canRedo: () => (stacks.value, undoManager.redoStack.length > 0),
275
+ presence: awareness ? (presence) => awareness.setLocalStateField("dashboard", presence) : void 0,
276
+ peers: awareness ? (id) => peersByWidget.value.get(id) ?? NO_PEERS : void 0
277
+ };
278
+ }
279
+ export { collaboration, collaborationColors, fillMap, readMap };
280
+
281
+ //# sourceMappingURL=index.js.map