@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
@@ -0,0 +1,68 @@
1
+ // src/widgets/shared.ts
2
+ /** The value at a dotted path, e.g. `total.amount`; the data itself for an empty path. */
3
+ function valueAt(data, path) {
4
+ if (!path) return data;
5
+ let value = data;
6
+ for (const key of path.split(".")) {
7
+ if (value == null || typeof value !== "object") return void 0;
8
+ value = value[key];
9
+ }
10
+ return value;
11
+ }
12
+ /** The rows of a source's data: the data when it is a list, or the list at `path`. */
13
+ function rowsOf(data, path) {
14
+ const value = valueAt(data, path);
15
+ return Array.isArray(value) ? value : [];
16
+ }
17
+ /** The keys of the first row of a list, or of an object: the fields to pick from in settings. */
18
+ function fieldsOf(data) {
19
+ const first = Array.isArray(data) ? data[0] : data;
20
+ return first && typeof first === "object" && !Array.isArray(first) ? Object.keys(first) : [];
21
+ }
22
+ /** The keys whose value in the first row is a number. */
23
+ function numberFieldsOf(data) {
24
+ const first = Array.isArray(data) ? data[0] : data;
25
+ return fieldsOf(data).filter((key) => typeof first[key] === "number");
26
+ }
27
+ /** A filter value from a value of the data: dates as `YYYY-MM-DD`, so the filters stay JSON. */
28
+ var pad = (n) => String(n).padStart(2, "0");
29
+ function filterValueOf(value) {
30
+ if (!(value instanceof Date)) return value;
31
+ return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}`;
32
+ }
33
+ /** A value of the data as a sheet cell's: dates as `YYYY-MM-DD`, text starting with `=` kept as text. */
34
+ function sheetValueOf(value) {
35
+ if (value == null) return null;
36
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
37
+ if (typeof value === "boolean") return value;
38
+ const text = value instanceof Date ? filterValueOf(value) : String(value);
39
+ return text.startsWith("=") ? `'${text}` : text;
40
+ }
41
+ /**
42
+ * Rows of data as a workbook, for the dashboard's export menu: one sheet,
43
+ * a bold head row with the columns' titles, a row per row of data. An
44
+ * empty `name` takes the widget's title.
45
+ */
46
+ function rowsToWorkbook(name, columns, rows) {
47
+ const colSizes = {};
48
+ columns.forEach((column, i) => column.width && (colSizes[i] = Math.round(column.width)));
49
+ return {
50
+ version: 1,
51
+ sheets: [{
52
+ name,
53
+ cells: [columns.map((column) => ({
54
+ value: sheetValueOf(column.title),
55
+ style: "head"
56
+ })), ...rows.map((row) => columns.map((column) => sheetValueOf(row[column.key])))],
57
+ freeze: {
58
+ rows: 1,
59
+ cols: 0
60
+ },
61
+ colSizes
62
+ }],
63
+ styles: { head: { bold: true } }
64
+ };
65
+ }
66
+ export { fieldsOf, filterValueOf, numberFieldsOf, rowsOf, rowsToWorkbook, valueAt };
67
+
68
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","names":[],"sources":["../../src/widgets/shared.ts"],"sourcesContent":["import type { SheetValue, SheetWorkbook } from '@dou-ui/sheet/core'\n\n/** The value at a dotted path, e.g. `total.amount`; the data itself for an empty path. */\nexport function valueAt(data: unknown, path: string | undefined): unknown {\n if (!path) return data\n let value = data\n for (const key of path.split('.')) {\n if (value == null || typeof value !== 'object') return undefined\n value = (value as Record<string, unknown>)[key]\n }\n return value\n}\n\n/** The rows of a source's data: the data when it is a list, or the list at `path`. */\nexport function rowsOf(data: unknown, path?: string): Record<string, unknown>[] {\n const value = valueAt(data, path)\n return Array.isArray(value) ? (value as Record<string, unknown>[]) : []\n}\n\n/** The keys of the first row of a list, or of an object: the fields to pick from in settings. */\nexport function fieldsOf(data: unknown): string[] {\n const first = Array.isArray(data) ? data[0] : data\n return first && typeof first === 'object' && !Array.isArray(first) ? Object.keys(first) : []\n}\n\n/** The keys whose value in the first row is a number. */\nexport function numberFieldsOf(data: unknown): string[] {\n const first = Array.isArray(data) ? data[0] : data\n return fieldsOf(data).filter((key) => typeof (first as Record<string, unknown>)[key] === 'number')\n}\n\n/** A filter value from a value of the data: dates as `YYYY-MM-DD`, so the filters stay JSON. */\nconst pad = (n: number) => String(n).padStart(2, '0')\n\nexport function filterValueOf(value: unknown): unknown {\n if (!(value instanceof Date)) return value\n return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}`\n}\n\n/** A value of the data as a sheet cell's: dates as `YYYY-MM-DD`, text starting with `=` kept as text. */\nfunction sheetValueOf(value: unknown): SheetValue {\n if (value == null) return null\n if (typeof value === 'number') return Number.isFinite(value) ? value : null\n if (typeof value === 'boolean') return value\n const text = value instanceof Date ? (filterValueOf(value) as string) : String(value)\n return text.startsWith('=') ? `'${text}` : text\n}\n\n/**\n * Rows of data as a workbook, for the dashboard's export menu: one sheet,\n * a bold head row with the columns' titles, a row per row of data. An\n * empty `name` takes the widget's title.\n */\nexport function rowsToWorkbook(\n name: string,\n columns: readonly { key: string; title: string; width?: number }[],\n rows: readonly Record<string, unknown>[],\n): SheetWorkbook {\n const colSizes: Record<number, number> = {}\n columns.forEach((column, i) => column.width && (colSizes[i] = Math.round(column.width)))\n return {\n version: 1,\n sheets: [\n {\n name,\n cells: [\n columns.map((column) => ({ value: sheetValueOf(column.title), style: 'head' })),\n ...rows.map((row) => columns.map((column) => sheetValueOf(row[column.key]))),\n ],\n freeze: { rows: 1, cols: 0 },\n colSizes,\n },\n ],\n styles: { head: { bold: true } },\n }\n}\n"],"mappings":";;AAGA,SAAgB,QAAQ,MAAe,MAAmC;CACxE,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,QAAQ;CACZ,KAAK,MAAM,OAAO,KAAK,MAAM,GAAG,GAAG;EACjC,IAAI,SAAS,QAAQ,OAAO,UAAU,UAAU,OAAO,KAAA;EACvD,QAAS,MAAkC;CAC7C;CACA,OAAO;AACT;;AAGA,SAAgB,OAAO,MAAe,MAA0C;CAC9E,MAAM,QAAQ,QAAQ,MAAM,IAAI;CAChC,OAAO,MAAM,QAAQ,KAAK,IAAK,QAAsC,CAAC;AACxE;;AAGA,SAAgB,SAAS,MAAyB;CAChD,MAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK;CAC9C,OAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC;AAC7F;;AAGA,SAAgB,eAAe,MAAyB;CACtD,MAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,KAAK,KAAK;CAC9C,OAAO,SAAS,IAAI,CAAC,CAAC,QAAQ,QAAQ,OAAQ,MAAkC,SAAS,QAAQ;AACnG;;AAGA,IAAM,OAAO,MAAc,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;AAEpD,SAAgB,cAAc,OAAyB;CACrD,IAAI,EAAE,iBAAiB,OAAO,OAAO;CACrC,OAAO,GAAG,MAAM,YAAY,EAAE,GAAG,IAAI,MAAM,SAAS,IAAI,CAAC,EAAE,GAAG,IAAI,MAAM,QAAQ,CAAC;AACnF;;AAGA,SAAS,aAAa,OAA4B;CAChD,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI,OAAO,UAAU,UAAU,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;CACvE,IAAI,OAAO,UAAU,WAAW,OAAO;CACvC,MAAM,OAAO,iBAAiB,OAAQ,cAAc,KAAK,IAAe,OAAO,KAAK;CACpF,OAAO,KAAK,WAAW,GAAG,IAAI,IAAI,SAAS;AAC7C;;;;;;AAOA,SAAgB,eACd,MACA,SACA,MACe;CACf,MAAM,WAAmC,CAAC;CAC1C,QAAQ,SAAS,QAAQ,MAAM,OAAO,UAAU,SAAS,KAAK,KAAK,MAAM,OAAO,KAAK,EAAE;CACvF,OAAO;EACL,SAAS;EACT,QAAQ,CACN;GACE;GACA,OAAO,CACL,QAAQ,KAAK,YAAY;IAAE,OAAO,aAAa,OAAO,KAAK;IAAG,OAAO;GAAO,EAAE,GAC9E,GAAG,KAAK,KAAK,QAAQ,QAAQ,KAAK,WAAW,aAAa,IAAI,OAAO,IAAI,CAAC,CAAC,CAC7E;GACA,QAAQ;IAAE,MAAM;IAAG,MAAM;GAAE;GAC3B;EACF,CACF;EACA,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE;CACjC;AACF"}
@@ -0,0 +1,6 @@
1
+ import source_field_vue_vue_type_script_setup_true_lang_default from "./source-field.vue_vue_type_script_setup_true_lang.js";
2
+ // src/widgets/source-field.vue
3
+ var source_field_default = source_field_vue_vue_type_script_setup_true_lang_default;
4
+ export { source_field_default as default };
5
+
6
+ //# sourceMappingURL=source-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-field.js","names":["_sfc_main"],"sources":["../../src/widgets/source-field.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouSelect } from 'dou-ui'\nimport { computed } from 'vue'\nimport { useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport SettingsField from './settings-field.vue'\n\ndefineOptions({ name: 'DouDashboardSourceField' })\n\n/** The source's name in the widget's `props.source`. */\nconst model = defineModel<string | undefined>()\nconst props = defineProps<{ optional?: boolean }>()\n\nconst messages = useDashboardMessages()\nconst { sources } = useDashboardWidget()\nconst options = computed(() => [\n ...(props.optional ? [{ value: '', label: messages.value.noSource }] : []),\n ...sources.value.map((name) => ({ value: name, label: name })),\n])\n</script>\n\n<template>\n <SettingsField :label=\"messages.source\">\n <DouSelect\n :model-value=\"model ?? ''\"\n :options=\"options\"\n :aria-label=\"messages.source\"\n @update:model-value=\"(value) => (model = (value as string) || undefined)\"\n />\n </SettingsField>\n</template>\n"],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import { useDashboardMessages } from "../locale.js";
2
+ import { useDashboardWidget } from "../widget/context.js";
3
+ import settings_field_default from "./settings-field.js";
4
+ import { DouSelect } from "dou-ui";
5
+ import { computed, createBlock, createVNode, defineComponent, mergeModels, openBlock, unref, useModel, withCtx } from "vue";
6
+ // src/widgets/source-field.vue?vue&type=script&setup=true&lang.ts
7
+ var source_field_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
8
+ name: "DouDashboardSourceField",
9
+ __name: "source-field",
10
+ props: /*@__PURE__*/ mergeModels({ optional: { type: Boolean } }, {
11
+ "modelValue": {},
12
+ "modelModifiers": {}
13
+ }),
14
+ emits: ["update:modelValue"],
15
+ setup(__props) {
16
+ /** The source's name in the widget's `props.source`. */
17
+ const model = useModel(__props, "modelValue");
18
+ const props = __props;
19
+ const messages = useDashboardMessages();
20
+ const { sources } = useDashboardWidget();
21
+ const options = computed(() => [...props.optional ? [{
22
+ value: "",
23
+ label: messages.value.noSource
24
+ }] : [], ...sources.value.map((name) => ({
25
+ value: name,
26
+ label: name
27
+ }))]);
28
+ return (_ctx, _cache) => {
29
+ return openBlock(), createBlock(settings_field_default, { label: unref(messages).source }, {
30
+ default: withCtx(() => [createVNode(unref(DouSelect), {
31
+ "model-value": model.value ?? "",
32
+ options: options.value,
33
+ "aria-label": unref(messages).source,
34
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = (value) => model.value = value || void 0)
35
+ }, null, 8, [
36
+ "model-value",
37
+ "options",
38
+ "aria-label"
39
+ ])]),
40
+ _: 1
41
+ }, 8, ["label"]);
42
+ };
43
+ }
44
+ });
45
+ export { source_field_vue_vue_type_script_setup_true_lang_default as default };
46
+
47
+ //# sourceMappingURL=source-field.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-field.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","SettingsField","_unref","_withCtx","_createVNode"],"sources":["../../src/widgets/source-field.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouSelect } from 'dou-ui'\nimport { computed } from 'vue'\nimport { useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport SettingsField from './settings-field.vue'\n\ndefineOptions({ name: 'DouDashboardSourceField' })\n\n/** The source's name in the widget's `props.source`. */\nconst model = defineModel<string | undefined>()\nconst props = defineProps<{ optional?: boolean }>()\n\nconst messages = useDashboardMessages()\nconst { sources } = useDashboardWidget()\nconst options = computed(() => [\n ...(props.optional ? [{ value: '', label: messages.value.noSource }] : []),\n ...sources.value.map((name) => ({ value: name, label: name })),\n])\n</script>\n\n<template>\n <SettingsField :label=\"messages.source\">\n <DouSelect\n :model-value=\"model ?? ''\"\n :options=\"options\"\n :aria-label=\"messages.source\"\n @update:model-value=\"(value) => (model = (value as string) || undefined)\"\n />\n </SettingsField>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAUA,MAAM,QAAQA,SAA+B,SAAA,YAAC;EAC9C,MAAM,QAAQ;EAEd,MAAM,WAAW,qBAAqB;EACtC,MAAM,EAAE,YAAY,mBAAmB;EACvC,MAAM,UAAU,eAAe,CAC7B,GAAI,MAAM,WAAW,CAAC;GAAE,OAAO;GAAI,OAAO,SAAS,MAAM;EAAS,CAAC,IAAI,CAAC,GACxE,GAAG,QAAQ,MAAM,KAAK,UAAU;GAAE,OAAO;GAAM,OAAO;EAAK,EAAE,CAC/D,CAAC;;GAIC,OAAAC,UAAA,GAAAC,YAOgBC,wBAAA,EAPA,OAAOC,MAAA,QAAA,CAAQ,CAAC,O;IAC9B,SAAAC,cAKE,CALFC,YAKEF,MAAA,SAAA,GAAA;KAJC,eAAa,MAAA,SAAK;KAClB,SAAS,QAAA;KACT,cAAYA,MAAA,QAAA,CAAQ,CAAC;KACrB,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAW,MAAA,QAAS,SAAoB,KAAA"}
@@ -0,0 +1,6 @@
1
+ import stat_settings_vue_vue_type_script_setup_true_lang_default from "./stat-settings.vue_vue_type_script_setup_true_lang.js";
2
+ // src/widgets/stat-settings.vue
3
+ var stat_settings_default = stat_settings_vue_vue_type_script_setup_true_lang_default;
4
+ export { stat_settings_default as default };
5
+
6
+ //# sourceMappingURL=stat-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-settings.js","names":["_sfc_main"],"sources":["../../src/widgets/stat-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouInput, DouInputNumber } from 'dou-ui'\nimport { computed } from 'vue'\nimport { useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport FieldSelect from './field-select.vue'\nimport SettingsField from './settings-field.vue'\nimport { fieldsOf } from './shared'\nimport SourceField from './source-field.vue'\nimport type { StatWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardStatSettings' })\n\nconst model = defineModel<StatWidgetProps>({ required: true })\nconst messages = useDashboardMessages()\nconst { data } = useDashboardWidget()\nconst fields = computed(() => fieldsOf(data.value))\nconst set = (patch: Partial<StatWidgetProps>) => (model.value = { ...model.value, ...patch })\n</script>\n\n<template>\n <div class=\"dou-dashboard__settings\">\n <SourceField\n :model-value=\"model.source\"\n optional\n @update:model-value=\"(source) => set({ source })\"\n />\n <FieldSelect\n v-if=\"model.source\"\n :model-value=\"model.field\"\n :label=\"messages.value\"\n :fields=\"fields\"\n @update:model-value=\"(field) => set({ field: field as string | undefined })\"\n />\n <SettingsField v-else :label=\"messages.value\">\n <DouInputNumber\n :model-value=\"model.value ?? null\"\n :aria-label=\"messages.value\"\n @update:model-value=\"(value) => set({ value: value ?? undefined })\"\n />\n </SettingsField>\n <div class=\"dou-dashboard__field-row\">\n <SettingsField :label=\"messages.prefix\">\n <DouInput\n :model-value=\"model.prefix ?? ''\"\n :aria-label=\"messages.prefix\"\n @update:model-value=\"(prefix) => set({ prefix: prefix || undefined })\"\n />\n </SettingsField>\n <SettingsField :label=\"messages.suffix\">\n <DouInput\n :model-value=\"model.suffix ?? ''\"\n :aria-label=\"messages.suffix\"\n @update:model-value=\"(suffix) => set({ suffix: suffix || undefined })\"\n />\n </SettingsField>\n </div>\n <SettingsField :label=\"messages.precision\">\n <DouInputNumber\n :model-value=\"model.precision ?? null\"\n :min=\"0\"\n :max=\"6\"\n :aria-label=\"messages.precision\"\n @update:model-value=\"(precision) => set({ precision: precision ?? undefined })\"\n />\n </SettingsField>\n <template v-if=\"model.source\">\n <FieldSelect\n :model-value=\"model.trend\"\n :label=\"messages.trend\"\n :fields=\"fields\"\n @update:model-value=\"(trend) => set({ trend: trend as string | undefined })\"\n />\n <FieldSelect\n :model-value=\"model.delta\"\n :label=\"messages.delta\"\n :fields=\"fields\"\n @update:model-value=\"(delta) => set({ delta: delta as string | undefined })\"\n />\n </template>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import { useDashboardMessages } from "../locale.js";
2
+ import { useDashboardWidget } from "../widget/context.js";
3
+ import { fieldsOf } from "./shared.js";
4
+ import settings_field_default from "./settings-field.js";
5
+ import field_select_default from "./field-select.js";
6
+ import source_field_default from "./source-field.js";
7
+ import { DouInput, DouInputNumber } from "dou-ui";
8
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, openBlock, unref, useModel, withCtx } from "vue";
9
+ // src/widgets/stat-settings.vue?vue&type=script&setup=true&lang.ts
10
+ var _hoisted_1 = { class: "dou-dashboard__settings" };
11
+ var _hoisted_2 = { class: "dou-dashboard__field-row" };
12
+ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
13
+ name: "DouDashboardStatSettings",
14
+ __name: "stat-settings",
15
+ props: {
16
+ "modelValue": { required: true },
17
+ "modelModifiers": {}
18
+ },
19
+ emits: ["update:modelValue"],
20
+ setup(__props) {
21
+ const model = useModel(__props, "modelValue");
22
+ const messages = useDashboardMessages();
23
+ const { data } = useDashboardWidget();
24
+ const fields = computed(() => fieldsOf(data.value));
25
+ const set = (patch) => model.value = {
26
+ ...model.value,
27
+ ...patch
28
+ };
29
+ return (_ctx, _cache) => {
30
+ return openBlock(), createElementBlock("div", _hoisted_1, [
31
+ createVNode(source_field_default, {
32
+ "model-value": model.value.source,
33
+ optional: "",
34
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = (source) => set({ source }))
35
+ }, null, 8, ["model-value"]),
36
+ model.value.source ? (openBlock(), createBlock(field_select_default, {
37
+ key: 0,
38
+ "model-value": model.value.field,
39
+ label: unref(messages).value,
40
+ fields: fields.value,
41
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = (field) => set({ field }))
42
+ }, null, 8, [
43
+ "model-value",
44
+ "label",
45
+ "fields"
46
+ ])) : (openBlock(), createBlock(settings_field_default, {
47
+ key: 1,
48
+ label: unref(messages).value
49
+ }, {
50
+ default: withCtx(() => [createVNode(unref(DouInputNumber), {
51
+ "model-value": model.value.value ?? null,
52
+ "aria-label": unref(messages).value,
53
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = (value) => set({ value: value ?? void 0 }))
54
+ }, null, 8, ["model-value", "aria-label"])]),
55
+ _: 1
56
+ }, 8, ["label"])),
57
+ createElementVNode("div", _hoisted_2, [createVNode(settings_field_default, { label: unref(messages).prefix }, {
58
+ default: withCtx(() => [createVNode(unref(DouInput), {
59
+ "model-value": model.value.prefix ?? "",
60
+ "aria-label": unref(messages).prefix,
61
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = (prefix) => set({ prefix: prefix || void 0 }))
62
+ }, null, 8, ["model-value", "aria-label"])]),
63
+ _: 1
64
+ }, 8, ["label"]), createVNode(settings_field_default, { label: unref(messages).suffix }, {
65
+ default: withCtx(() => [createVNode(unref(DouInput), {
66
+ "model-value": model.value.suffix ?? "",
67
+ "aria-label": unref(messages).suffix,
68
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = (suffix) => set({ suffix: suffix || void 0 }))
69
+ }, null, 8, ["model-value", "aria-label"])]),
70
+ _: 1
71
+ }, 8, ["label"])]),
72
+ createVNode(settings_field_default, { label: unref(messages).precision }, {
73
+ default: withCtx(() => [createVNode(unref(DouInputNumber), {
74
+ "model-value": model.value.precision ?? null,
75
+ min: 0,
76
+ max: 6,
77
+ "aria-label": unref(messages).precision,
78
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = (precision) => set({ precision: precision ?? void 0 }))
79
+ }, null, 8, ["model-value", "aria-label"])]),
80
+ _: 1
81
+ }, 8, ["label"]),
82
+ model.value.source ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(field_select_default, {
83
+ "model-value": model.value.trend,
84
+ label: unref(messages).trend,
85
+ fields: fields.value,
86
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = (trend) => set({ trend }))
87
+ }, null, 8, [
88
+ "model-value",
89
+ "label",
90
+ "fields"
91
+ ]), createVNode(field_select_default, {
92
+ "model-value": model.value.delta,
93
+ label: unref(messages).delta,
94
+ fields: fields.value,
95
+ "onUpdate:modelValue": _cache[7] || (_cache[7] = (delta) => set({ delta }))
96
+ }, null, 8, [
97
+ "model-value",
98
+ "label",
99
+ "fields"
100
+ ])], 64)) : createCommentVNode("", true)
101
+ ]);
102
+ };
103
+ }
104
+ });
105
+ export { stat_settings_vue_vue_type_script_setup_true_lang_default as default };
106
+
107
+ //# sourceMappingURL=stat-settings.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-settings.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createVNode","SourceField","_createBlock","FieldSelect","_unref","SettingsField","_withCtx","_createElementVNode","_Fragment","_createCommentVNode"],"sources":["../../src/widgets/stat-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouInput, DouInputNumber } from 'dou-ui'\nimport { computed } from 'vue'\nimport { useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport FieldSelect from './field-select.vue'\nimport SettingsField from './settings-field.vue'\nimport { fieldsOf } from './shared'\nimport SourceField from './source-field.vue'\nimport type { StatWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardStatSettings' })\n\nconst model = defineModel<StatWidgetProps>({ required: true })\nconst messages = useDashboardMessages()\nconst { data } = useDashboardWidget()\nconst fields = computed(() => fieldsOf(data.value))\nconst set = (patch: Partial<StatWidgetProps>) => (model.value = { ...model.value, ...patch })\n</script>\n\n<template>\n <div class=\"dou-dashboard__settings\">\n <SourceField\n :model-value=\"model.source\"\n optional\n @update:model-value=\"(source) => set({ source })\"\n />\n <FieldSelect\n v-if=\"model.source\"\n :model-value=\"model.field\"\n :label=\"messages.value\"\n :fields=\"fields\"\n @update:model-value=\"(field) => set({ field: field as string | undefined })\"\n />\n <SettingsField v-else :label=\"messages.value\">\n <DouInputNumber\n :model-value=\"model.value ?? null\"\n :aria-label=\"messages.value\"\n @update:model-value=\"(value) => set({ value: value ?? undefined })\"\n />\n </SettingsField>\n <div class=\"dou-dashboard__field-row\">\n <SettingsField :label=\"messages.prefix\">\n <DouInput\n :model-value=\"model.prefix ?? ''\"\n :aria-label=\"messages.prefix\"\n @update:model-value=\"(prefix) => set({ prefix: prefix || undefined })\"\n />\n </SettingsField>\n <SettingsField :label=\"messages.suffix\">\n <DouInput\n :model-value=\"model.suffix ?? ''\"\n :aria-label=\"messages.suffix\"\n @update:model-value=\"(suffix) => set({ suffix: suffix || undefined })\"\n />\n </SettingsField>\n </div>\n <SettingsField :label=\"messages.precision\">\n <DouInputNumber\n :model-value=\"model.precision ?? null\"\n :min=\"0\"\n :max=\"6\"\n :aria-label=\"messages.precision\"\n @update:model-value=\"(precision) => set({ precision: precision ?? undefined })\"\n />\n </SettingsField>\n <template v-if=\"model.source\">\n <FieldSelect\n :model-value=\"model.trend\"\n :label=\"messages.trend\"\n :fields=\"fields\"\n @update:model-value=\"(trend) => set({ trend: trend as string | undefined })\"\n />\n <FieldSelect\n :model-value=\"model.delta\"\n :label=\"messages.delta\"\n :fields=\"fields\"\n @update:model-value=\"(delta) => set({ delta: delta as string | undefined })\"\n />\n </template>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAaA,MAAM,QAAQA,SAA4B,SAAA,YAAmB;EAC7D,MAAM,WAAW,qBAAqB;EACtC,MAAM,EAAE,SAAS,mBAAmB;EACpC,MAAM,SAAS,eAAe,SAAS,KAAK,KAAK,CAAC;EAClD,MAAM,OAAO,UAAqC,MAAM,QAAQ;GAAE,GAAG,MAAM;GAAO,GAAG;EAAM;;GAIzF,OAAAC,UAAA,GAAAC,mBA2DM,OA3DN,YA2DM;IA1DJC,YAIEC,sBAAA;KAHC,eAAa,MAAA,MAAM;KACpB,UAAA;KACC,uBAAkB,OAAA,OAAA,OAAA,MAAG,WAAW,IAAG,EAAG,OAAM,CAAA;;IAGvC,MAAA,MAAM,UADdH,UAAA,GAAAI,YAMEC,sBAAA;;KAJC,eAAa,MAAA,MAAM;KACnB,OAAOC,MAAA,QAAA,CAAQ,CAAC;KAChB,QAAQ,OAAA;KACR,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAU,IAAG,EAAU,MAAK,CAAA;;;;;I,OAEpDN,UAAA,GAAAI,YAMgBG,wBAAA;;KANO,OAAOD,MAAA,QAAA,CAAQ,CAAC;;KACrC,SAAAE,cAIE,CAJFN,YAIEI,MAAA,cAAA,GAAA;MAHC,eAAa,MAAA,MAAM,SAAK;MACxB,cAAYA,MAAA,QAAA,CAAQ,CAAC;MACrB,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAU,IAAG,EAAA,OAAU,SAAS,KAAA,EAAS,CAAA;;;;IAGnEG,mBAeM,OAfN,YAeM,CAdJP,YAMgBK,wBAAA,EANA,OAAOD,MAAA,QAAA,CAAQ,CAAC,O;KAC9B,SAAAE,cAIE,CAJFN,YAIEI,MAAA,QAAA,GAAA;MAHC,eAAa,MAAA,MAAM,UAAM;MACzB,cAAYA,MAAA,QAAA,CAAQ,CAAC;MACrB,uBAAkB,OAAA,OAAA,OAAA,MAAG,WAAW,IAAG,EAAA,QAAW,UAAU,KAAA,EAAS,CAAA;;;I,kBAGtEJ,YAMgBK,wBAAA,EANA,OAAOD,MAAA,QAAA,CAAQ,CAAC,O;KAC9B,SAAAE,cAIE,CAJFN,YAIEI,MAAA,QAAA,GAAA;MAHC,eAAa,MAAA,MAAM,UAAM;MACzB,cAAYA,MAAA,QAAA,CAAQ,CAAC;MACrB,uBAAkB,OAAA,OAAA,OAAA,MAAG,WAAW,IAAG,EAAA,QAAW,UAAU,KAAA,EAAS,CAAA;;;;IAIxEJ,YAQgBK,wBAAA,EARA,OAAOD,MAAA,QAAA,CAAQ,CAAC,U;KAC9B,SAAAE,cAME,CANFN,YAMEI,MAAA,cAAA,GAAA;MALC,eAAa,MAAA,MAAM,aAAS;MAC5B,KAAK;MACL,KAAK;MACL,cAAYA,MAAA,QAAA,CAAQ,CAAC;MACrB,uBAAkB,OAAA,OAAA,OAAA,MAAG,cAAc,IAAG,EAAA,WAAc,aAAa,KAAA,EAAS,CAAA;;;;IAG/D,MAAA,MAAM,UAAtBN,UAAA,GAAAC,mBAaWS,UAAA,EAAA,KAAA,EAAA,GAAA,CAZTR,YAKEG,sBAAA;KAJC,eAAa,MAAA,MAAM;KACnB,OAAOC,MAAA,QAAA,CAAQ,CAAC;KAChB,QAAQ,OAAA;KACR,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAU,IAAG,EAAU,MAAK,CAAA;;;;;I,IAEpDJ,YAKEG,sBAAA;KAJC,eAAa,MAAA,MAAM;KACnB,OAAOC,MAAA,QAAA,CAAQ,CAAC;KAChB,QAAQ,OAAA;KACR,uBAAkB,OAAA,OAAA,OAAA,MAAG,UAAU,IAAG,EAAU,MAAK,CAAA"}
@@ -0,0 +1,6 @@
1
+ import stat_vue_vue_type_script_setup_true_lang_default from "./stat.vue_vue_type_script_setup_true_lang.js";
2
+ // src/widgets/stat.vue
3
+ var stat_default = stat_vue_vue_type_script_setup_true_lang_default;
4
+ export { stat_default as default };
5
+
6
+ //# sourceMappingURL=stat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.js","names":["_sfc_main"],"sources":["../../src/widgets/stat.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouSparkline, DouStatistic } from 'dou-ui'\nimport { computed } from 'vue'\nimport { format, useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport { valueAt } from './shared'\nimport type { StatWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardStatWidget' })\n\nconst { props, data, size } = useDashboardWidget<StatWidgetProps>()\nconst messages = useDashboardMessages()\n\nconst value = computed(() => {\n const { field, value: fixed } = props.value\n if (!field) return fixed ?? null\n const read = Number(valueAt(data.value, field))\n return Number.isFinite(read) ? read : null\n})\nconst delta = computed(() => {\n const read = props.value.delta ? Number(valueAt(data.value, props.value.delta)) : Number.NaN\n return Number.isFinite(read) ? read : undefined\n})\nconst deltaText = computed(() => {\n if (delta.value === undefined) return ''\n const percent = `${delta.value > 0 ? '+' : ''}${(delta.value * 100).toFixed(1)}%`\n return format(messages.value.deltaText, { value: percent })\n})\nconst points = computed(() => {\n const list = props.value.trend ? valueAt(data.value, props.value.trend) : undefined\n return Array.isArray(list) ? list.map(Number).filter(Number.isFinite) : []\n})\n/** The sparkline takes what the number leaves of the height, out to the card's edges. */\nconst sparkHeight = computed(() => Math.max(0, Math.floor(size.height.value - 56)))\n</script>\n\n<template>\n <div class=\"dou-dashboard-stat\">\n <DouStatistic\n :value=\"value\"\n :precision=\"props.precision\"\n :prefix=\"props.prefix\"\n :suffix=\"props.suffix\"\n :trend=\"delta === undefined || delta === 0 ? undefined : delta > 0 ? 'up' : 'down'\"\n >\n <template v-if=\"deltaText\" #footer>{{ deltaText }}</template>\n </DouStatistic>\n <div v-if=\"points.length > 1 && sparkHeight >= 24\" class=\"dou-dashboard-stat__spark\">\n <DouSparkline\n :data=\"points\"\n type=\"area\"\n smooth\n :width=\"size.width.value + 32\"\n :height=\"sparkHeight\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,72 @@
1
+ import { format, useDashboardMessages } from "../locale.js";
2
+ import { useDashboardWidget } from "../widget/context.js";
3
+ import { valueAt } from "./shared.js";
4
+ import { DouSparkline, DouStatistic } from "dou-ui";
5
+ import { computed, createCommentVNode, createElementBlock, createSlots, createTextVNode, createVNode, defineComponent, openBlock, toDisplayString, unref, withCtx } from "vue";
6
+ // src/widgets/stat.vue?vue&type=script&setup=true&lang.ts
7
+ var _hoisted_1 = { class: "dou-dashboard-stat" };
8
+ var _hoisted_2 = {
9
+ key: 0,
10
+ class: "dou-dashboard-stat__spark"
11
+ };
12
+ var stat_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
13
+ name: "DouDashboardStatWidget",
14
+ __name: "stat",
15
+ setup(__props) {
16
+ const { props, data, size } = useDashboardWidget();
17
+ const messages = useDashboardMessages();
18
+ const value = computed(() => {
19
+ const { field, value: fixed } = props.value;
20
+ if (!field) return fixed ?? null;
21
+ const read = Number(valueAt(data.value, field));
22
+ return Number.isFinite(read) ? read : null;
23
+ });
24
+ const delta = computed(() => {
25
+ const read = props.value.delta ? Number(valueAt(data.value, props.value.delta)) : NaN;
26
+ return Number.isFinite(read) ? read : void 0;
27
+ });
28
+ const deltaText = computed(() => {
29
+ if (delta.value === void 0) return "";
30
+ const percent = `${delta.value > 0 ? "+" : ""}${(delta.value * 100).toFixed(1)}%`;
31
+ return format(messages.value.deltaText, { value: percent });
32
+ });
33
+ const points = computed(() => {
34
+ const list = props.value.trend ? valueAt(data.value, props.value.trend) : void 0;
35
+ return Array.isArray(list) ? list.map(Number).filter(Number.isFinite) : [];
36
+ });
37
+ /** The sparkline takes what the number leaves of the height, out to the card's edges. */
38
+ const sparkHeight = computed(() => Math.max(0, Math.floor(size.height.value - 56)));
39
+ return (_ctx, _cache) => {
40
+ return openBlock(), createElementBlock("div", _hoisted_1, [createVNode(unref(DouStatistic), {
41
+ value: value.value,
42
+ precision: unref(props).precision,
43
+ prefix: unref(props).prefix,
44
+ suffix: unref(props).suffix,
45
+ trend: delta.value === void 0 || delta.value === 0 ? void 0 : delta.value > 0 ? "up" : "down"
46
+ }, createSlots({ _: 2 }, [deltaText.value ? {
47
+ name: "footer",
48
+ fn: withCtx(() => [createTextVNode(toDisplayString(deltaText.value), 1)]),
49
+ key: "0"
50
+ } : void 0]), 1032, [
51
+ "value",
52
+ "precision",
53
+ "prefix",
54
+ "suffix",
55
+ "trend"
56
+ ]), points.value.length > 1 && sparkHeight.value >= 24 ? (openBlock(), createElementBlock("div", _hoisted_2, [createVNode(unref(DouSparkline), {
57
+ data: points.value,
58
+ type: "area",
59
+ smooth: "",
60
+ width: unref(size).width.value + 32,
61
+ height: sparkHeight.value
62
+ }, null, 8, [
63
+ "data",
64
+ "width",
65
+ "height"
66
+ ])])) : createCommentVNode("", true)]);
67
+ };
68
+ }
69
+ });
70
+ export { stat_vue_vue_type_script_setup_true_lang_default as default };
71
+
72
+ //# sourceMappingURL=stat.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createVNode","_unref","_createSlots","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode"],"sources":["../../src/widgets/stat.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouSparkline, DouStatistic } from 'dou-ui'\nimport { computed } from 'vue'\nimport { format, useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport { valueAt } from './shared'\nimport type { StatWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardStatWidget' })\n\nconst { props, data, size } = useDashboardWidget<StatWidgetProps>()\nconst messages = useDashboardMessages()\n\nconst value = computed(() => {\n const { field, value: fixed } = props.value\n if (!field) return fixed ?? null\n const read = Number(valueAt(data.value, field))\n return Number.isFinite(read) ? read : null\n})\nconst delta = computed(() => {\n const read = props.value.delta ? Number(valueAt(data.value, props.value.delta)) : Number.NaN\n return Number.isFinite(read) ? read : undefined\n})\nconst deltaText = computed(() => {\n if (delta.value === undefined) return ''\n const percent = `${delta.value > 0 ? '+' : ''}${(delta.value * 100).toFixed(1)}%`\n return format(messages.value.deltaText, { value: percent })\n})\nconst points = computed(() => {\n const list = props.value.trend ? valueAt(data.value, props.value.trend) : undefined\n return Array.isArray(list) ? list.map(Number).filter(Number.isFinite) : []\n})\n/** The sparkline takes what the number leaves of the height, out to the card's edges. */\nconst sparkHeight = computed(() => Math.max(0, Math.floor(size.height.value - 56)))\n</script>\n\n<template>\n <div class=\"dou-dashboard-stat\">\n <DouStatistic\n :value=\"value\"\n :precision=\"props.precision\"\n :prefix=\"props.prefix\"\n :suffix=\"props.suffix\"\n :trend=\"delta === undefined || delta === 0 ? undefined : delta > 0 ? 'up' : 'down'\"\n >\n <template v-if=\"deltaText\" #footer>{{ deltaText }}</template>\n </DouStatistic>\n <div v-if=\"points.length > 1 && sparkHeight >= 24\" class=\"dou-dashboard-stat__spark\">\n <DouSparkline\n :data=\"points\"\n type=\"area\"\n smooth\n :width=\"size.width.value + 32\"\n :height=\"sparkHeight\"\n />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;EAUA,MAAM,EAAE,OAAO,MAAM,SAAS,mBAAoC;EAClE,MAAM,WAAW,qBAAqB;EAEtC,MAAM,QAAQ,eAAe;GAC3B,MAAM,EAAE,OAAO,OAAO,UAAU,MAAM;GACtC,IAAI,CAAC,OAAO,OAAO,SAAS;GAC5B,MAAM,OAAO,OAAO,QAAQ,KAAK,OAAO,KAAK,CAAC;GAC9C,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO;EACxC,CAAC;EACD,MAAM,QAAQ,eAAe;GAC3B,MAAM,OAAO,MAAM,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,MAAM,MAAM,KAAK,CAAC,IAAI;GAClF,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO,KAAA;EACxC,CAAC;EACD,MAAM,YAAY,eAAe;GAC/B,IAAI,MAAM,UAAU,KAAA,GAAW,OAAO;GACtC,MAAM,UAAU,GAAG,MAAM,QAAQ,IAAI,MAAM,MAAM,MAAM,QAAQ,IAAA,CAAK,QAAQ,CAAC,EAAE;GAC/E,OAAO,OAAO,SAAS,MAAM,WAAW,EAAE,OAAO,QAAQ,CAAC;EAC5D,CAAC;EACD,MAAM,SAAS,eAAe;GAC5B,MAAM,OAAO,MAAM,MAAM,QAAQ,QAAQ,KAAK,OAAO,MAAM,MAAM,KAAK,IAAI,KAAA;GAC1E,OAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,MAAM,CAAC,CAAC,OAAO,OAAO,QAAQ,IAAI,CAAC;EAC3E,CAAC;;EAED,MAAM,cAAc,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,OAAO,QAAQ,EAAE,CAAC,CAAC;;GAIhF,OAAAA,UAAA,GAAAC,mBAmBM,OAnBN,YAmBM,CAlBJC,YAQeC,MAAA,YAAA,GAAA;IAPZ,OAAO,MAAA;IACP,WAAWA,MAAA,KAAA,CAAK,CAAC;IACjB,QAAQA,MAAA,KAAA,CAAK,CAAC;IACd,QAAQA,MAAA,KAAA,CAAK,CAAC;IACd,OAAO,MAAA,UAAU,KAAA,KAAa,MAAA,UAAK,IAAS,KAAA,IAAY,MAAA,QAAK,IAAA,OAAA;G,0BAE9C,UAAA,Q;IAAY,MAAA;IAAO,IAAAE,cAAe,CAAZC,gBAAAC,gBAAA,UAAA,KAAS,GAAA,CAAA,C;;;;;;;;G,IAEtC,OAAA,MAAO,SAAM,KAAQ,YAAA,SAAW,MAA3CP,UAAA,GAAAC,mBAQM,OARN,YAQM,CAPJC,YAMEC,MAAA,YAAA,GAAA;IALC,MAAM,OAAA;IACP,MAAK;IACL,QAAA;IACC,OAAOA,MAAA,IAAA,CAAI,CAAC,MAAM,QAAK;IACvB,QAAQ,YAAA"}
@@ -0,0 +1,6 @@
1
+ import table_settings_vue_vue_type_script_setup_true_lang_default from "./table-settings.vue_vue_type_script_setup_true_lang.js";
2
+ // src/widgets/table-settings.vue
3
+ var table_settings_default = table_settings_vue_vue_type_script_setup_true_lang_default;
4
+ export { table_settings_default as default };
5
+
6
+ //# sourceMappingURL=table-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-settings.js","names":["_sfc_main"],"sources":["../../src/widgets/table-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouCheckbox, DouInput } from 'dou-ui'\nimport { computed } from 'vue'\nimport { format, useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport SettingsField from './settings-field.vue'\nimport { fieldsOf, rowsOf } from './shared'\nimport SourceField from './source-field.vue'\nimport type { TableWidgetColumn, TableWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardTableSettings' })\n\nconst model = defineModel<TableWidgetProps>({ required: true })\nconst messages = useDashboardMessages()\nconst { data } = useDashboardWidget()\n\n/** Every field of the rows, those shown first in their order. */\nconst fields = computed(() => {\n const all = fieldsOf(rowsOf(data.value, model.value.path))\n const shown = model.value.columns?.map((column) => column.key) ?? all\n return [...shown, ...all.filter((key) => !shown.includes(key))]\n})\nconst columns = computed<TableWidgetColumn[]>(\n () =>\n model.value.columns ?? fieldsOf(rowsOf(data.value, model.value.path)).map((key) => ({ key })),\n)\nconst columnOf = (key: string) => columns.value.find((column) => column.key === key)\n\nfunction toggle(key: string, on: boolean) {\n const next = on\n ? [...columns.value, { key }]\n : columns.value.filter((column) => column.key !== key)\n model.value = { ...model.value, columns: next }\n}\n\nfunction retitle(key: string, title: string) {\n const next = columns.value.map((column) =>\n column.key === key ? { key, ...(title ? { title } : {}) } : column,\n )\n model.value = { ...model.value, columns: next }\n}\n</script>\n\n<template>\n <div class=\"dou-dashboard__settings\">\n <SourceField\n :model-value=\"model.source\"\n @update:model-value=\"(source) => (model = { ...model, source })\"\n />\n <SettingsField v-if=\"fields.length\" :label=\"messages.columns\">\n <div class=\"dou-dashboard__columns\">\n <div v-for=\"key in fields\" :key=\"key\" class=\"dou-dashboard__column\">\n <DouCheckbox\n :model-value=\"!!columnOf(key)\"\n @update:model-value=\"(on) => toggle(key, !!on)\"\n >\n {{ key }}\n </DouCheckbox>\n <DouInput\n v-if=\"columnOf(key)\"\n size=\"sm\"\n :model-value=\"columnOf(key)?.title ?? ''\"\n :placeholder=\"key\"\n :aria-label=\"format(messages.columnTitle, { field: key })\"\n @update:model-value=\"(title) => retitle(key, title)\"\n />\n </div>\n </div>\n </SettingsField>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import { format, useDashboardMessages } from "../locale.js";
2
+ import { useDashboardWidget } from "../widget/context.js";
3
+ import { fieldsOf, rowsOf } from "./shared.js";
4
+ import settings_field_default from "./settings-field.js";
5
+ import source_field_default from "./source-field.js";
6
+ import { DouCheckbox, DouInput } from "dou-ui";
7
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, renderList, toDisplayString, unref, useModel, withCtx } from "vue";
8
+ // src/widgets/table-settings.vue?vue&type=script&setup=true&lang.ts
9
+ var _hoisted_1 = { class: "dou-dashboard__settings" };
10
+ var _hoisted_2 = { class: "dou-dashboard__columns" };
11
+ var table_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
12
+ name: "DouDashboardTableSettings",
13
+ __name: "table-settings",
14
+ props: {
15
+ "modelValue": { required: true },
16
+ "modelModifiers": {}
17
+ },
18
+ emits: ["update:modelValue"],
19
+ setup(__props) {
20
+ const model = useModel(__props, "modelValue");
21
+ const messages = useDashboardMessages();
22
+ const { data } = useDashboardWidget();
23
+ /** Every field of the rows, those shown first in their order. */
24
+ const fields = computed(() => {
25
+ const all = fieldsOf(rowsOf(data.value, model.value.path));
26
+ const shown = model.value.columns?.map((column) => column.key) ?? all;
27
+ return [...shown, ...all.filter((key) => !shown.includes(key))];
28
+ });
29
+ const columns = computed(() => model.value.columns ?? fieldsOf(rowsOf(data.value, model.value.path)).map((key) => ({ key })));
30
+ const columnOf = (key) => columns.value.find((column) => column.key === key);
31
+ function toggle(key, on) {
32
+ const next = on ? [...columns.value, { key }] : columns.value.filter((column) => column.key !== key);
33
+ model.value = {
34
+ ...model.value,
35
+ columns: next
36
+ };
37
+ }
38
+ function retitle(key, title) {
39
+ const next = columns.value.map((column) => column.key === key ? {
40
+ key,
41
+ ...title ? { title } : {}
42
+ } : column);
43
+ model.value = {
44
+ ...model.value,
45
+ columns: next
46
+ };
47
+ }
48
+ return (_ctx, _cache) => {
49
+ return openBlock(), createElementBlock("div", _hoisted_1, [createVNode(source_field_default, {
50
+ "model-value": model.value.source,
51
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = (source) => model.value = {
52
+ ...model.value,
53
+ source
54
+ })
55
+ }, null, 8, ["model-value"]), fields.value.length ? (openBlock(), createBlock(settings_field_default, {
56
+ key: 0,
57
+ label: unref(messages).columns
58
+ }, {
59
+ default: withCtx(() => [createElementVNode("div", _hoisted_2, [(openBlock(true), createElementBlock(Fragment, null, renderList(fields.value, (key) => {
60
+ return openBlock(), createElementBlock("div", {
61
+ key,
62
+ class: "dou-dashboard__column"
63
+ }, [createVNode(unref(DouCheckbox), {
64
+ "model-value": !!columnOf(key),
65
+ "onUpdate:modelValue": (on) => toggle(key, !!on)
66
+ }, {
67
+ default: withCtx(() => [createTextVNode(toDisplayString(key), 1)]),
68
+ _: 2
69
+ }, 1032, ["model-value", "onUpdate:modelValue"]), columnOf(key) ? (openBlock(), createBlock(unref(DouInput), {
70
+ key: 0,
71
+ size: "sm",
72
+ "model-value": columnOf(key)?.title ?? "",
73
+ placeholder: key,
74
+ "aria-label": unref(format)(unref(messages).columnTitle, { field: key }),
75
+ "onUpdate:modelValue": (title) => retitle(key, title)
76
+ }, null, 8, [
77
+ "model-value",
78
+ "placeholder",
79
+ "aria-label",
80
+ "onUpdate:modelValue"
81
+ ])) : createCommentVNode("", true)]);
82
+ }), 128))])]),
83
+ _: 1
84
+ }, 8, ["label"])) : createCommentVNode("", true)]);
85
+ };
86
+ }
87
+ });
88
+ export { table_settings_vue_vue_type_script_setup_true_lang_default as default };
89
+
90
+ //# sourceMappingURL=table-settings.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-settings.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createVNode","SourceField","_createBlock","SettingsField","_unref","_withCtx","_createElementVNode","_Fragment","_renderList","_createTextVNode","_toDisplayString","_createCommentVNode"],"sources":["../../src/widgets/table-settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouCheckbox, DouInput } from 'dou-ui'\nimport { computed } from 'vue'\nimport { format, useDashboardMessages } from '../locale'\nimport { useDashboardWidget } from '../widget/context'\nimport SettingsField from './settings-field.vue'\nimport { fieldsOf, rowsOf } from './shared'\nimport SourceField from './source-field.vue'\nimport type { TableWidgetColumn, TableWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardTableSettings' })\n\nconst model = defineModel<TableWidgetProps>({ required: true })\nconst messages = useDashboardMessages()\nconst { data } = useDashboardWidget()\n\n/** Every field of the rows, those shown first in their order. */\nconst fields = computed(() => {\n const all = fieldsOf(rowsOf(data.value, model.value.path))\n const shown = model.value.columns?.map((column) => column.key) ?? all\n return [...shown, ...all.filter((key) => !shown.includes(key))]\n})\nconst columns = computed<TableWidgetColumn[]>(\n () =>\n model.value.columns ?? fieldsOf(rowsOf(data.value, model.value.path)).map((key) => ({ key })),\n)\nconst columnOf = (key: string) => columns.value.find((column) => column.key === key)\n\nfunction toggle(key: string, on: boolean) {\n const next = on\n ? [...columns.value, { key }]\n : columns.value.filter((column) => column.key !== key)\n model.value = { ...model.value, columns: next }\n}\n\nfunction retitle(key: string, title: string) {\n const next = columns.value.map((column) =>\n column.key === key ? { key, ...(title ? { title } : {}) } : column,\n )\n model.value = { ...model.value, columns: next }\n}\n</script>\n\n<template>\n <div class=\"dou-dashboard__settings\">\n <SourceField\n :model-value=\"model.source\"\n @update:model-value=\"(source) => (model = { ...model, source })\"\n />\n <SettingsField v-if=\"fields.length\" :label=\"messages.columns\">\n <div class=\"dou-dashboard__columns\">\n <div v-for=\"key in fields\" :key=\"key\" class=\"dou-dashboard__column\">\n <DouCheckbox\n :model-value=\"!!columnOf(key)\"\n @update:model-value=\"(on) => toggle(key, !!on)\"\n >\n {{ key }}\n </DouCheckbox>\n <DouInput\n v-if=\"columnOf(key)\"\n size=\"sm\"\n :model-value=\"columnOf(key)?.title ?? ''\"\n :placeholder=\"key\"\n :aria-label=\"format(messages.columnTitle, { field: key })\"\n @update:model-value=\"(title) => retitle(key, title)\"\n />\n </div>\n </div>\n </SettingsField>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAYA,MAAM,QAAQA,SAA6B,SAAA,YAAmB;EAC9D,MAAM,WAAW,qBAAqB;EACtC,MAAM,EAAE,SAAS,mBAAmB;;EAGpC,MAAM,SAAS,eAAe;GAC5B,MAAM,MAAM,SAAS,OAAO,KAAK,OAAO,MAAM,MAAM,IAAI,CAAC;GACzD,MAAM,QAAQ,MAAM,MAAM,SAAS,KAAK,WAAW,OAAO,GAAG,KAAK;GAClE,OAAO,CAAC,GAAG,OAAO,GAAG,IAAI,QAAQ,QAAQ,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;EAChE,CAAC;EACD,MAAM,UAAU,eAEZ,MAAM,MAAM,WAAW,SAAS,OAAO,KAAK,OAAO,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,IAAI,EAAE,CAChG;EACA,MAAM,YAAY,QAAgB,QAAQ,MAAM,MAAM,WAAW,OAAO,QAAQ,GAAG;EAEnF,SAAS,OAAO,KAAa,IAAa;GACxC,MAAM,OAAO,KACT,CAAC,GAAG,QAAQ,OAAO,EAAE,IAAI,CAAC,IAC1B,QAAQ,MAAM,QAAQ,WAAW,OAAO,QAAQ,GAAG;GACvD,MAAM,QAAQ;IAAE,GAAG,MAAM;IAAO,SAAS;GAAK;EAChD;EAEA,SAAS,QAAQ,KAAa,OAAe;GAC3C,MAAM,OAAO,QAAQ,MAAM,KAAK,WAC9B,OAAO,QAAQ,MAAM;IAAE;IAAK,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;GAAG,IAAI,MAC9D;GACA,MAAM,QAAQ;IAAE,GAAG,MAAM;IAAO,SAAS;GAAK;EAChD;;GAIE,OAAAC,UAAA,GAAAC,mBAyBM,OAzBN,YAyBM,CAxBJC,YAGEC,sBAAA;IAFC,eAAa,MAAA,MAAM;IACnB,uBAAkB,OAAA,OAAA,OAAA,MAAG,WAAY,MAAA,QAAK;KAAA,GAAQ,MAAA;KAAO;IAAM;G,8BAEzC,OAAA,MAAO,UAA5BH,UAAA,GAAAI,YAmBgBC,wBAAA;;IAnBqB,OAAOC,MAAA,QAAA,CAAQ,CAAC;;IACnD,SAAAC,cAiBM,CAjBNC,mBAiBM,OAjBN,YAiBM,EAhBJR,UAAA,IAAA,GAAAC,mBAeMQ,UAAA,MAAAC,WAfa,OAAA,QAAP,QAAG;KAAf,OAAAV,UAAA,GAAAC,mBAeM,OAAA;MAf2B;MAAK,OAAM;K,IAC1CC,YAKcI,MAAA,WAAA,GAAA;MAJX,eAAW,CAAA,CAAI,SAAS,GAAG;MAC3B,wBAAqB,OAAO,OAAO,KAAG,CAAA,CAAI,EAAE;;MAE7C,SAAAC,cAAS,CAANI,gBAAAC,gBAAA,GAAG,GAAA,CAAA,C;;K,kDAGA,SAAS,GAAG,KADpBZ,UAAA,GAAAI,YAOEE,MAAA,QAAA,GAAA;;MALA,MAAK;MACJ,eAAa,SAAS,GAAG,CAAA,EAAG,SAAK;MACjC,aAAa;MACb,cAAYA,MAAA,MAAA,CAAM,CAACA,MAAA,QAAA,CAAQ,CAAC,aAAW,EAAA,OAAW,IAAG,CAAA;MACrD,wBAAqB,UAAU,QAAQ,KAAK,KAAK"}
@@ -0,0 +1,6 @@
1
+ import table_vue_vue_type_script_setup_true_lang_default from "./table.vue_vue_type_script_setup_true_lang.js";
2
+ // src/widgets/table.vue
3
+ var table_default = table_vue_vue_type_script_setup_true_lang_default;
4
+ export { table_default as default };
5
+
6
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","names":["_sfc_main"],"sources":["../../src/widgets/table.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { DouTable } from 'dou-ui'\nimport type { TableColumn } from 'dou-ui'\nimport { computed, onMounted, ref } from 'vue'\nimport { useDashboardWidget } from '../widget/context'\nimport { fieldsOf, rowsToWorkbook, rowsOf } from './shared'\nimport type { TableWidgetColumn, TableWidgetProps } from './types'\n\ndefineOptions({ name: 'DouDashboardTableWidget' })\n\nconst { props, data, size, setWorkbook } = useDashboardWidget<TableWidgetProps>()\nconst rows = computed(() => rowsOf(data.value, props.value.path))\n/** Each row's key: its `rowKey` field, or its place in the list. */\nconst keys = computed(() => {\n const map = new WeakMap<object, string | number>()\n const field = props.value.rowKey\n rows.value.forEach((row, index) => map.set(row, field ? (row[field] as string | number) : index))\n return map\n})\nconst rowKey = (row: Record<string, unknown>) => keys.value.get(row) ?? ''\nconst number = new Intl.NumberFormat()\n/** The table's font, read once it is on the page, to measure texts with. */\nconst root = ref<{ $el: Element }>()\nconst font = ref('')\nonMounted(() => {\n const cell = root.value?.$el.querySelector('td, th')\n if (cell) font.value = getComputedStyle(cell).font\n})\nlet context: CanvasRenderingContext2D | null | undefined\n/** How wide a text is in the table's font, or about how wide before it is known. */\nfunction textWidth(text: string) {\n context ??=\n typeof document === 'undefined' ? null : document.createElement('canvas').getContext('2d')\n if (context && font.value) {\n context.font = font.value\n return context.measureText(text).width\n }\n let width = 0\n for (const char of text) width += char.charCodeAt(0) > 0x2e7f ? 14 : 8.5\n return width\n}\n/** Room for the title and the first rows' texts, with the cell's padding; up to 240px. */\nfunction minWidthOf(title: string, texts: unknown[]) {\n let widest = textWidth(title)\n for (const text of texts) widest = Math.max(widest, textWidth(String(text ?? '')))\n return Math.min(240, Math.ceil(widest) + 28)\n}\nconst columns = computed<TableColumn[]>(() => {\n const first = rows.value[0]\n const list: TableWidgetColumn[] =\n props.value.columns ?? fieldsOf(rows.value).map((key) => ({ key }))\n return list.map(({ key, title }) => {\n const numeric = typeof first?.[key] === 'number'\n // numbers with digit groups, as in the stat widget\n const value = numeric\n ? (row: Record<string, unknown>) =>\n typeof row[key] === 'number' ? number.format(row[key] as number) : row[key]\n : undefined\n const sample = rows.value.slice(0, 20).map((row) => (value ? value(row) : row[key]))\n const least = minWidthOf(title || key, sample)\n return {\n key,\n title: title || key,\n align: numeric ? 'end' : undefined,\n ellipsis: true,\n // shares of the width follow the contents; never narrower than them\n width: least,\n minWidth: least,\n value,\n }\n })\n})\n// the export menu writes the rows as they are, numbers without digit groups\nsetWorkbook(() =>\n rowsToWorkbook(\n '',\n columns.value.map((column) => ({\n key: column.key as string,\n title: String(column.title),\n width: typeof column.width === 'number' ? column.width : undefined,\n })),\n rows.value,\n ),\n)\n</script>\n\n<template>\n <DouTable\n ref=\"root\"\n class=\"dou-dashboard-table\"\n :data=\"rows\"\n :columns=\"columns\"\n :row-key=\"rowKey\"\n size=\"sm\"\n :max-height=\"size.height.value || undefined\"\n :virtual=\"rows.length > 100\"\n />\n</template>\n"],"mappings":""}
@@ -0,0 +1,91 @@
1
+ import { useDashboardWidget } from "../widget/context.js";
2
+ import { fieldsOf, rowsOf, rowsToWorkbook } from "./shared.js";
3
+ import { DouTable } from "dou-ui";
4
+ import { computed, createBlock, defineComponent, onMounted, openBlock, ref, unref } from "vue";
5
+ // src/widgets/table.vue?vue&type=script&setup=true&lang.ts
6
+ var table_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
+ name: "DouDashboardTableWidget",
8
+ __name: "table",
9
+ setup(__props) {
10
+ const { props, data, size, setWorkbook } = useDashboardWidget();
11
+ const rows = computed(() => rowsOf(data.value, props.value.path));
12
+ /** Each row's key: its `rowKey` field, or its place in the list. */
13
+ const keys = computed(() => {
14
+ const map = /* @__PURE__ */ new WeakMap();
15
+ const field = props.value.rowKey;
16
+ rows.value.forEach((row, index) => map.set(row, field ? row[field] : index));
17
+ return map;
18
+ });
19
+ const rowKey = (row) => keys.value.get(row) ?? "";
20
+ const number = new Intl.NumberFormat();
21
+ /** The table's font, read once it is on the page, to measure texts with. */
22
+ const root = ref();
23
+ const font = ref("");
24
+ onMounted(() => {
25
+ const cell = root.value?.$el.querySelector("td, th");
26
+ if (cell) font.value = getComputedStyle(cell).font;
27
+ });
28
+ let context;
29
+ /** How wide a text is in the table's font, or about how wide before it is known. */
30
+ function textWidth(text) {
31
+ context ??= typeof document === "undefined" ? null : document.createElement("canvas").getContext("2d");
32
+ if (context && font.value) {
33
+ context.font = font.value;
34
+ return context.measureText(text).width;
35
+ }
36
+ let width = 0;
37
+ for (const char of text) width += char.charCodeAt(0) > 11903 ? 14 : 8.5;
38
+ return width;
39
+ }
40
+ /** Room for the title and the first rows' texts, with the cell's padding; up to 240px. */
41
+ function minWidthOf(title, texts) {
42
+ let widest = textWidth(title);
43
+ for (const text of texts) widest = Math.max(widest, textWidth(String(text ?? "")));
44
+ return Math.min(240, Math.ceil(widest) + 28);
45
+ }
46
+ const columns = computed(() => {
47
+ const first = rows.value[0];
48
+ return (props.value.columns ?? fieldsOf(rows.value).map((key) => ({ key }))).map(({ key, title }) => {
49
+ const numeric = typeof first?.[key] === "number";
50
+ const value = numeric ? (row) => typeof row[key] === "number" ? number.format(row[key]) : row[key] : void 0;
51
+ const sample = rows.value.slice(0, 20).map((row) => value ? value(row) : row[key]);
52
+ const least = minWidthOf(title || key, sample);
53
+ return {
54
+ key,
55
+ title: title || key,
56
+ align: numeric ? "end" : void 0,
57
+ ellipsis: true,
58
+ width: least,
59
+ minWidth: least,
60
+ value
61
+ };
62
+ });
63
+ });
64
+ setWorkbook(() => rowsToWorkbook("", columns.value.map((column) => ({
65
+ key: column.key,
66
+ title: String(column.title),
67
+ width: typeof column.width === "number" ? column.width : void 0
68
+ })), rows.value));
69
+ return (_ctx, _cache) => {
70
+ return openBlock(), createBlock(unref(DouTable), {
71
+ ref_key: "root",
72
+ ref: root,
73
+ class: "dou-dashboard-table",
74
+ data: rows.value,
75
+ columns: columns.value,
76
+ "row-key": rowKey,
77
+ size: "sm",
78
+ "max-height": unref(size).height.value || void 0,
79
+ virtual: rows.value.length > 100
80
+ }, null, 8, [
81
+ "data",
82
+ "columns",
83
+ "max-height",
84
+ "virtual"
85
+ ]);
86
+ };
87
+ }
88
+ });
89
+ export { table_vue_vue_type_script_setup_true_lang_default as default };
90
+
91
+ //# sourceMappingURL=table.vue_vue_type_script_setup_true_lang.js.map