@dou-ui/dashboard 0.1.0-alpha.3 → 0.1.0-alpha.5

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 (97) hide show
  1. package/dist/chart/chart-settings.js.map +1 -1
  2. package/dist/chart/chart-settings.vue_vue_type_script_setup_true_lang.js +10 -8
  3. package/dist/chart/chart-settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  4. package/dist/chart/chart.js.map +1 -1
  5. package/dist/chart/chart.vue_vue_type_script_setup_true_lang.js +19 -15
  6. package/dist/chart/chart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/chart/read-props.js +26 -0
  8. package/dist/chart/read-props.js.map +1 -0
  9. package/dist/core/document.js +10 -1
  10. package/dist/core/document.js.map +1 -1
  11. package/dist/core/history.js +23 -0
  12. package/dist/core/history.js.map +1 -1
  13. package/dist/core/transaction.js +8 -2
  14. package/dist/core/transaction.js.map +1 -1
  15. package/dist/dashboard/comment-button.js +6 -0
  16. package/dist/dashboard/comment-button.js.map +1 -0
  17. package/dist/dashboard/comment-button.vue_vue_type_script_setup_true_lang.js +59 -0
  18. package/dist/dashboard/comment-button.vue_vue_type_script_setup_true_lang.js.map +1 -0
  19. package/dist/dashboard/comment-card.js +6 -0
  20. package/dist/dashboard/comment-card.js.map +1 -0
  21. package/dist/dashboard/comment-card.vue_vue_type_script_setup_true_lang.js +128 -0
  22. package/dist/dashboard/comment-card.vue_vue_type_script_setup_true_lang.js.map +1 -0
  23. package/dist/dashboard/comments.js +144 -0
  24. package/dist/dashboard/comments.js.map +1 -0
  25. package/dist/dashboard/dashboard.js.map +1 -1
  26. package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js +132 -20
  27. package/dist/dashboard/dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/dashboard/error-boundary.js +64 -0
  29. package/dist/dashboard/error-boundary.js.map +1 -0
  30. package/dist/dashboard/frame-context.js.map +1 -1
  31. package/dist/dashboard/widget-body.js.map +1 -1
  32. package/dist/dashboard/widget-body.vue_vue_type_script_setup_true_lang.js +53 -12
  33. package/dist/dashboard/widget-body.vue_vue_type_script_setup_true_lang.js.map +1 -1
  34. package/dist/dashboard/widget-frame.js.map +1 -1
  35. package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js +14 -2
  36. package/dist/dashboard/widget-frame.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/dashboard/widget-settings.js.map +1 -1
  38. package/dist/dashboard/widget-settings.vue_vue_type_script_setup_true_lang.js +31 -5
  39. package/dist/dashboard/widget-settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/locale.js +12 -0
  42. package/dist/locale.js.map +1 -1
  43. package/dist/pivot/pivot-settings.js.map +1 -1
  44. package/dist/pivot/pivot-settings.vue_vue_type_script_setup_true_lang.js +6 -4
  45. package/dist/pivot/pivot-settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  46. package/dist/pivot/pivot.js.map +1 -1
  47. package/dist/pivot/pivot.vue_vue_type_script_setup_true_lang.js +4 -2
  48. package/dist/pivot/pivot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/pivot/read-props.js +44 -0
  50. package/dist/pivot/read-props.js.map +1 -0
  51. package/dist/style.css +1 -1
  52. package/dist/style.js +2 -3
  53. package/dist/types/chart/read-props.d.ts +3 -0
  54. package/dist/types/core/document.d.ts +3 -2
  55. package/dist/types/core/history.d.ts +7 -1
  56. package/dist/types/core/transaction.d.ts +10 -1
  57. package/dist/types/core/types.d.ts +5 -0
  58. package/dist/types/dashboard/comment-button.vue.d.ts +15 -0
  59. package/dist/types/dashboard/comment-card.vue.d.ts +13 -0
  60. package/dist/types/dashboard/comments.d.ts +44 -0
  61. package/dist/types/dashboard/dashboard.vue.d.ts +12 -0
  62. package/dist/types/dashboard/error-boundary.d.ts +12 -0
  63. package/dist/types/dashboard/frame-context.d.ts +4 -0
  64. package/dist/types/dashboard/types.d.ts +47 -0
  65. package/dist/types/dashboard/widget-body.vue.d.ts +2 -0
  66. package/dist/types/dashboard/widget-settings.vue.d.ts +4 -0
  67. package/dist/types/index.d.ts +22 -1
  68. package/dist/types/locale.d.ts +8 -0
  69. package/dist/types/pivot/read-props.d.ts +3 -0
  70. package/dist/types/widgets/index.d.ts +1 -1
  71. package/dist/types/widgets/read-props.d.ts +4 -0
  72. package/dist/types/widgets/shared.d.ts +20 -4
  73. package/dist/widgets/index.js +2 -2
  74. package/dist/widgets/index.js.map +1 -1
  75. package/dist/widgets/read-props.js +52 -0
  76. package/dist/widgets/read-props.js.map +1 -0
  77. package/dist/widgets/shared.js +27 -5
  78. package/dist/widgets/shared.js.map +1 -1
  79. package/dist/widgets/stat-settings.js.map +1 -1
  80. package/dist/widgets/stat-settings.vue_vue_type_script_setup_true_lang.js +12 -10
  81. package/dist/widgets/stat-settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/widgets/stat.js.map +1 -1
  83. package/dist/widgets/stat.vue_vue_type_script_setup_true_lang.js +10 -13
  84. package/dist/widgets/stat.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/widgets/table-settings.js.map +1 -1
  86. package/dist/widgets/table-settings.vue_vue_type_script_setup_true_lang.js +6 -4
  87. package/dist/widgets/table-settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/widgets/table.js.map +1 -1
  89. package/dist/widgets/table.vue_vue_type_script_setup_true_lang.js +3 -1
  90. package/dist/widgets/table.vue_vue_type_script_setup_true_lang.js.map +1 -1
  91. package/dist/widgets/text-settings.js.map +1 -1
  92. package/dist/widgets/text-settings.vue_vue_type_script_setup_true_lang.js +5 -3
  93. package/dist/widgets/text-settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  94. package/dist/widgets/text.js.map +1 -1
  95. package/dist/widgets/text.vue_vue_type_script_setup_true_lang.js +5 -3
  96. package/dist/widgets/text.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/package.json +8 -8
@@ -15,19 +15,31 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, Das
15
15
  breakpointChange: (breakpoint: string) => any;
16
16
  "update:filters": (value: DashboardFilters) => any;
17
17
  exportError: (event: DashboardExportErrorEvent) => any;
18
+ widgetError: (event: import("./types").DashboardWidgetErrorEvent) => any;
19
+ "update:comments": (threads: import("dou-ui").CommentThread[]) => any;
20
+ "update:activeComment": (id: string | null) => any;
21
+ commentAction: (action: import("dou-ui").CommentAction) => any;
18
22
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
19
23
  onChange?: ((transaction: DashboardTransaction) => any) | undefined;
20
24
  "onUpdate:modelValue"?: ((value: DashboardDocument) => any) | undefined;
21
25
  onBreakpointChange?: ((breakpoint: string) => any) | undefined;
22
26
  "onUpdate:filters"?: ((value: DashboardFilters) => any) | undefined;
23
27
  onExportError?: ((event: DashboardExportErrorEvent) => any) | undefined;
28
+ onWidgetError?: ((event: import("./types").DashboardWidgetErrorEvent) => any) | undefined;
29
+ "onUpdate:comments"?: ((threads: import("dou-ui").CommentThread[]) => any) | undefined;
30
+ "onUpdate:activeComment"?: ((id: string | null) => any) | undefined;
31
+ onCommentAction?: ((action: import("dou-ui").CommentAction) => any) | undefined;
24
32
  }>, {
33
+ comments: import("dou-ui").CommentThread[];
25
34
  columns: number | Record<string, number>;
26
35
  breakpoints: Record<string, number>;
27
36
  rowHeight: number;
28
37
  gap: number | [number, number];
29
38
  compact: import("..").GridCompact;
30
39
  widgets: DashboardWidgetType<any>[];
40
+ author: import("dou-ui").CommentAuthor;
41
+ activeComment: string | null;
42
+ commentable: boolean;
31
43
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
32
44
  declare const _default: typeof __VLS_export;
33
45
  export default _default;
@@ -0,0 +1,12 @@
1
+ import type { Ref } from 'vue';
2
+ /**
3
+ * Whether an error broke what a component shows. Errors in event handlers,
4
+ * watchers and the like leave it showing: they go on to the app as usual.
5
+ */
6
+ export declare function breaksView(info: string): boolean;
7
+ /**
8
+ * Keeps an error that breaks a widget's content or settings in that part:
9
+ * `failed` turns on, `report` is told, and the error goes no further. The
10
+ * caller shows the error state and turns `failed` off to try again.
11
+ */
12
+ export declare function useErrorBoundary(label: () => string, report: (error: unknown) => void): Ref<boolean>;
@@ -1,6 +1,7 @@
1
1
  import type { SheetWorkbook } from '@dou-ui/sheet/core';
2
2
  import type { Component, InjectionKey } from 'vue';
3
3
  import type { DashboardPeer } from '../core/collaboration';
4
+ import type { DashboardComments } from './comments';
4
5
  import type { DashboardWidget } from '../core/types';
5
6
  import type { DashboardLinkedFilter } from '../data/types';
6
7
  import type { DashboardMessages } from '../locale';
@@ -18,6 +19,7 @@ export interface FrameExporter {
18
19
  * that widget's frame again, not every frame on the grid.
19
20
  */
20
21
  export interface FrameContext {
22
+ comments: DashboardComments;
21
23
  widget: (id: string) => DashboardWidget | undefined;
22
24
  type: (widget: DashboardWidget) => DashboardWidgetType<any> | undefined;
23
25
  title: (widget: DashboardWidget) => string;
@@ -50,5 +52,7 @@ export interface FrameContext {
50
52
  /** Why the last export from a widget's menu failed. */
51
53
  exportError: (id: string) => string | undefined;
52
54
  clearExportError: (id: string) => void;
55
+ /** A widget's content broke, for `widgetError`. */
56
+ reportError: (id: string, error: unknown) => void;
53
57
  }
54
58
  export declare const frameContextKey: InjectionKey<FrameContext>;
@@ -1,3 +1,4 @@
1
+ import type { CommentAction, CommentAuthor, CommentThread } from 'dou-ui';
1
2
  import type { SheetExporterOptionsOf } from '@dou-ui/sheet';
2
3
  import type { SheetExporter } from '@dou-ui/sheet/core';
3
4
  import type { DashboardCollaboration } from '../core/collaboration';
@@ -8,6 +9,10 @@ import type { GridCompact } from '../layout/types';
8
9
  import type { DashboardMessagesOverride } from '../locale';
9
10
  import type { DashboardWidgetType } from '../widget/define';
10
11
  import type { DashboardImageOptions } from './export';
12
+ /** What a comment thread is about: a widget. */
13
+ export interface DashboardCommentAnchor {
14
+ widget: string;
15
+ }
11
16
  export interface DashboardProps {
12
17
  /** The dashboard, bound with `v-model`; a new document object after every change. */
13
18
  modelValue?: DashboardDocument;
@@ -58,6 +63,18 @@ export interface DashboardProps {
58
63
  * such as PNG, are left out.
59
64
  */
60
65
  exporters?: readonly SheetExporter[];
66
+ /**
67
+ * The comment threads, bound with `v-model:comments`. The widget a thread
68
+ * is about keeps the thread's id in its `comments`. Left out, there are
69
+ * no comments.
70
+ */
71
+ comments?: CommentThread[];
72
+ /** Who is commenting. Without it comments can be read but not written. */
73
+ author?: CommentAuthor;
74
+ /** The thread open now, bound with `v-model:activeComment`. */
75
+ activeComment?: string | null;
76
+ /** Threads can be started and replied to; also while not `editable`. On by default. */
77
+ commentable?: boolean;
61
78
  }
62
79
  /** Options of a dashboard's `exportWidget`. */
63
80
  export interface DashboardExportOptions<Options = any> {
@@ -71,6 +88,17 @@ export interface DashboardSaveOptions<Options = any> extends DashboardExportOpti
71
88
  /** The file's name, with its extension; the widget's title by default. */
72
89
  fileName?: string;
73
90
  }
91
+ /**
92
+ * A widget's component threw while setting up or drawing its content or
93
+ * settings form; that part shows an error with a retry button instead.
94
+ */
95
+ export interface DashboardWidgetErrorEvent {
96
+ /** The widget's id. */
97
+ widget: string;
98
+ /** Which part broke: what the widget shows, or its settings form. */
99
+ part: 'content' | 'settings';
100
+ error: unknown;
101
+ }
74
102
  /** A widget's export from its menu failed. */
75
103
  export interface DashboardExportErrorEvent {
76
104
  /** The widget's id. */
@@ -92,6 +120,16 @@ export interface DashboardEmits {
92
120
  breakpointChange: [breakpoint: string];
93
121
  /** Exporting a widget from its menu or `saveWidget` failed; the widget tells of it unless prevented. */
94
122
  exportError: [event: DashboardExportErrorEvent];
123
+ /**
124
+ * A widget's content or settings form threw while it set up or drew; it
125
+ * shows an error in its place, and the error goes no further. To report
126
+ * to error tracking.
127
+ */
128
+ widgetError: [event: DashboardWidgetErrorEvent];
129
+ 'update:comments': [threads: CommentThread[]];
130
+ 'update:activeComment': [id: string | null];
131
+ /** A change to the comments made here: to send to a server, notify people, keep a log. */
132
+ commentAction: [action: CommentAction];
95
133
  }
96
134
  export interface DashboardAddOptions {
97
135
  /** Where on the widest breakpoint; defaults to the first spot it fits. */
@@ -114,6 +152,15 @@ export interface DashboardExpose {
114
152
  /** Adds a widget of a registered type; returns its id, or `undefined` for an unknown type. */
115
153
  addWidget: (type: string, options?: DashboardAddOptions) => string | undefined;
116
154
  removeWidget: (id: string) => void;
155
+ /**
156
+ * Opens the open threads on a widget (the one holding the focus when
157
+ * left out), ready to reply, or starts one there; `false` when there is
158
+ * no such widget, comments are off, or there is nothing to open and
159
+ * comments can't be written.
160
+ */
161
+ comment: (id?: string) => boolean;
162
+ /** The widget each thread is about; `null` when it is gone. Not reactive. */
163
+ getCommentAnchors: () => Record<string, DashboardCommentAnchor | null>;
117
164
  /** Adds a copy of a widget next to it; returns the copy's id. */
118
165
  duplicateWidget: (id: string) => string | undefined;
119
166
  focusWidget: (id: string) => void;
@@ -13,6 +13,8 @@ type __VLS_Props = {
13
13
  }) => void;
14
14
  /** Where the widget's workbook goes, for its export menu; the full-screen copy has none. */
15
15
  setWorkbook?: (id: string, get: () => SheetWorkbook | undefined) => () => void;
16
+ /** Told when the widget's content breaks, for the dashboard's `widgetError`. */
17
+ reportError?: (id: string, error: unknown) => void;
16
18
  };
17
19
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
20
  declare const _default: typeof __VLS_export;
@@ -1,11 +1,15 @@
1
1
  import type { DashboardWidget } from '../core/types';
2
+ import type { DashboardMessages } from '../locale';
2
3
  import type { DashboardWidgetType } from '../widget/define';
3
4
  type __VLS_Props = {
4
5
  widget: DashboardWidget;
5
6
  type: DashboardWidgetType<any>;
7
+ messages: DashboardMessages;
6
8
  setProps: (id: string, patch: Record<string, unknown>, options?: {
7
9
  group?: string;
8
10
  }) => void;
11
+ /** Told when the settings form breaks, for the dashboard's `widgetError`. */
12
+ reportError?: (id: string, error: unknown) => void;
9
13
  };
10
14
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
15
  "update:props": (props: Record<string, unknown>) => any;
@@ -154,6 +154,7 @@ export declare const DouGridLayoutHandle: import("dou-ui").WithInstall<{
154
154
  };
155
155
  }), import("vue").HTMLAttributes>;
156
156
  export declare const DouDashboard: import("dou-ui").WithInstall<import("vue").DefineComponent<{
157
+ comments?: import("dou-ui").CommentThread[] | undefined;
157
158
  columns?: (number | Record<string, number>) | undefined;
158
159
  editable?: boolean | undefined;
159
160
  label?: string | undefined;
@@ -167,6 +168,9 @@ export declare const DouDashboard: import("dou-ui").WithInstall<import("vue").De
167
168
  createId?: ((type: string) => string) | undefined;
168
169
  collaboration?: import("./index.js").DashboardCollaboration | undefined;
169
170
  exporters?: readonly import("@dou-ui/sheet").SheetExporter[] | undefined;
171
+ author?: import("dou-ui").CommentAuthor | undefined;
172
+ activeComment?: string | null | undefined;
173
+ commentable?: boolean | undefined;
170
174
  } & {
171
175
  modelValue?: import("./index.js").DashboardDocument;
172
176
  filters?: import("./index.js").DashboardFilters;
@@ -176,7 +180,12 @@ export declare const DouDashboard: import("dou-ui").WithInstall<import("vue").De
176
180
  breakpointChange: (breakpoint: string) => any;
177
181
  "update:filters": (value: import("./index.js").DashboardFilters) => any;
178
182
  exportError: (event: import("./index.js").DashboardExportErrorEvent) => any;
183
+ widgetError: (event: import("./index.js").DashboardWidgetErrorEvent) => any;
184
+ "update:comments": (threads: import("dou-ui").CommentThread[]) => any;
185
+ "update:activeComment": (id: string | null) => any;
186
+ commentAction: (action: import("dou-ui").CommentAction) => any;
179
187
  }, string, import("vue").PublicProps, Readonly<{
188
+ comments?: import("dou-ui").CommentThread[] | undefined;
180
189
  columns?: (number | Record<string, number>) | undefined;
181
190
  editable?: boolean | undefined;
182
191
  label?: string | undefined;
@@ -190,6 +199,9 @@ export declare const DouDashboard: import("dou-ui").WithInstall<import("vue").De
190
199
  createId?: ((type: string) => string) | undefined;
191
200
  collaboration?: import("./index.js").DashboardCollaboration | undefined;
192
201
  exporters?: readonly import("@dou-ui/sheet").SheetExporter[] | undefined;
202
+ author?: import("dou-ui").CommentAuthor | undefined;
203
+ activeComment?: string | null | undefined;
204
+ commentable?: boolean | undefined;
193
205
  } & {
194
206
  modelValue?: import("./index.js").DashboardDocument;
195
207
  filters?: import("./index.js").DashboardFilters;
@@ -199,13 +211,21 @@ export declare const DouDashboard: import("dou-ui").WithInstall<import("vue").De
199
211
  onBreakpointChange?: ((breakpoint: string) => any) | undefined;
200
212
  "onUpdate:filters"?: ((value: import("./index.js").DashboardFilters) => any) | undefined;
201
213
  onExportError?: ((event: import("./index.js").DashboardExportErrorEvent) => any) | undefined;
214
+ onWidgetError?: ((event: import("./index.js").DashboardWidgetErrorEvent) => any) | undefined;
215
+ "onUpdate:comments"?: ((threads: import("dou-ui").CommentThread[]) => any) | undefined;
216
+ "onUpdate:activeComment"?: ((id: string | null) => any) | undefined;
217
+ onCommentAction?: ((action: import("dou-ui").CommentAction) => any) | undefined;
202
218
  }>, {
219
+ comments: import("dou-ui").CommentThread[];
203
220
  columns: number | Record<string, number>;
204
221
  breakpoints: Record<string, number>;
205
222
  rowHeight: number;
206
223
  gap: number | [number, number];
207
224
  compact: import("./layout").GridCompact;
208
225
  widgets: import("./index.js").DashboardWidgetType<any>[];
226
+ author: import("dou-ui").CommentAuthor;
227
+ activeComment: string | null;
228
+ commentable: boolean;
209
229
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, import("vue").HTMLAttributes>;
210
230
  export declare const DouDashboardPalette: import("dou-ui").WithInstall<{
211
231
  new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("./index.js").DashboardPaletteProps> & Readonly<{}>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
@@ -264,11 +284,12 @@ export declare const DouDashboardFilterBar: import("dou-ui").WithInstall<{
264
284
  default?: () => unknown;
265
285
  };
266
286
  }), import("vue").HTMLAttributes>;
267
- export type { DashboardAddOptions, DashboardEmits, DashboardExportErrorEvent, DashboardExportOptions, DashboardSaveOptions, DashboardExpose, DashboardFilterBarProps, DashboardPaletteProps, DashboardProps, } from './dashboard/types';
287
+ export type { DashboardAddOptions, DashboardEmits, DashboardExportErrorEvent, DashboardWidgetErrorEvent, DashboardExportOptions, DashboardSaveOptions, DashboardCommentAnchor, DashboardExpose, DashboardFilterBarProps, DashboardPaletteProps, DashboardProps, } from './dashboard/types';
268
288
  export type { DashboardDocument, DashboardPlace, DashboardWidget } from './core/types';
269
289
  export { checkDocument, emptyDocument, isDashboardPlace, migrateDocument } from './core/document';
270
290
  export type { CheckDocumentOptions, DocumentProblem } from './core/document';
271
291
  export { applySteps, DashboardTransaction, replaceWidgets, sameValue } from './core/transaction';
292
+ export type { ReplaceWidgetsOptions } from './core/transaction';
272
293
  export type { DashboardCollaboration, DashboardCollaborationHost, DashboardPeer, DashboardPresence, DashboardPresenceAction, } from './core/collaboration';
273
294
  export type { DashboardStep, DashboardTransactionMeta, DashboardWidgetPatch, } from './core/transaction';
274
295
  export { DashboardHistory } from './core/history';
@@ -37,6 +37,10 @@ export interface DashboardMessages {
37
37
  nothingToExport: string;
38
38
  duplicate: string;
39
39
  remove: string;
40
+ /** The comment button and the card of a widget's discussions. */
41
+ comment: string;
42
+ /** The comment button of a widget with discussions; `{count}` is how many are open. */
43
+ comments: string;
40
44
  /** The settings drawer's title: `{title}`. */
41
45
  settingsTitle: string;
42
46
  /** The title field in the settings drawer. */
@@ -49,6 +53,10 @@ export interface DashboardMessages {
49
53
  /** A widget's status. */
50
54
  loading: string;
51
55
  error: string;
56
+ /** A widget that failed to show, e.g. for props it can't use. */
57
+ renderError: string;
58
+ /** A widget's settings form that failed to show. */
59
+ settingsError: string;
52
60
  empty: string;
53
61
  retry: string;
54
62
  /** A dashboard without widgets, while editing. */
@@ -0,0 +1,3 @@
1
+ import type { PivotWidgetProps } from './types';
2
+ /** The pivot widget's props as its type says; what isn't the right type counts as not set. */
3
+ export declare function pivotPropsOf(props: Record<string, unknown>): PivotWidgetProps;
@@ -1,7 +1,7 @@
1
1
  import type { DashboardWidgetType } from '../widget/define';
2
2
  import type { StatWidgetProps, TableWidgetProps, TextWidgetProps } from './types';
3
3
  export type { StatWidgetProps, TableWidgetColumn, TableWidgetProps, TextWidgetProps } from './types';
4
- export { fieldsOf, filterValueOf, numberFieldsOf, rowsOf, valueAt } from './shared';
4
+ export { fieldsOf, filterValueOf, flagOf, numberFieldsOf, numberOf, recordOf, rowsOf, textOf, textsOf, valueAt, } from './shared';
5
5
  /** What a built-in widget's definition can change: its type, label, icon, size and more. */
6
6
  export type WidgetOverrides<P extends object> = Partial<Omit<DashboardWidgetType<P>, 'component'>>;
7
7
  /**
@@ -0,0 +1,4 @@
1
+ import type { StatWidgetProps, TableWidgetProps, TextWidgetProps } from './types';
2
+ export declare function statPropsOf(props: Record<string, unknown>): StatWidgetProps;
3
+ export declare function textPropsOf(props: Record<string, unknown>): TextWidgetProps;
4
+ export declare function tablePropsOf(props: Record<string, unknown>): TableWidgetProps;
@@ -1,8 +1,24 @@
1
1
  import type { SheetWorkbook } from '@dou-ui/sheet/core';
2
- /** The value at a dotted path, e.g. `total.amount`; the data itself for an empty path. */
3
- export declare function valueAt(data: unknown, path: string | undefined): unknown;
4
- /** The rows of a source's data: the data when it is a list, or the list at `path`. */
5
- export declare function rowsOf(data: unknown, path?: string): Record<string, unknown>[];
2
+ /**
3
+ * The value at a dotted path, e.g. `total.amount`; the data itself for an
4
+ * empty path. A path that isn't text, e.g. a number in JSON written by hand
5
+ * or by a program, finds nothing.
6
+ */
7
+ export declare function valueAt(data: unknown, path: unknown): unknown;
8
+ /** The rows of a source's data: the data when it is a list, or the list at `path`. Items that aren't objects are left out. */
9
+ export declare function rowsOf(data: unknown, path?: unknown): Record<string, unknown>[];
10
+ /** Text, or not set. */
11
+ export declare const textOf: (value: unknown) => string | undefined;
12
+ /** A list of texts: the texts in it, or none. */
13
+ export declare const textsOf: (value: unknown) => string[];
14
+ /** A finite number, or text that is one (`'12'`, as a number read from data); otherwise not set. */
15
+ export declare function numberOf(value: unknown): number | undefined;
16
+ /** On only for `true`: `'no'` or `1` don't turn a switch on. */
17
+ export declare const flagOf: (value: unknown) => boolean;
18
+ /** A plain object, not a list; otherwise not set. */
19
+ export declare const recordOf: (value: unknown) => Record<string, unknown> | undefined;
20
+ /** One of the values listed, or not set. */
21
+ export declare const oneOf: <T extends string>(value: unknown, values: readonly T[]) => T | undefined;
6
22
  /** The keys of the first row of a list, or of an object: the fields to pick from in settings. */
7
23
  export declare function fieldsOf(data: unknown): string[];
8
24
  /** The keys whose value in the first row is a number. */
@@ -1,5 +1,5 @@
1
1
  import { defineDashboardWidget } from "../widget/define.js";
2
- import { fieldsOf, filterValueOf, numberFieldsOf, rowsOf, valueAt } from "./shared.js";
2
+ import { fieldsOf, filterValueOf, flagOf, numberFieldsOf, numberOf, recordOf, rowsOf, textOf, textsOf, valueAt } from "./shared.js";
3
3
  import stat_default from "./stat.js";
4
4
  import stat_settings_default from "./stat-settings.js";
5
5
  import table_default from "./table.js";
@@ -69,6 +69,6 @@ function tableWidget(overrides = {}) {
69
69
  ...overrides
70
70
  });
71
71
  }
72
- export { fieldsOf, filterValueOf, numberFieldsOf, rowsOf, statWidget, tableWidget, textWidget, valueAt };
72
+ export { fieldsOf, filterValueOf, flagOf, numberFieldsOf, numberOf, recordOf, rowsOf, statWidget, tableWidget, textOf, textWidget, textsOf, valueAt };
73
73
 
74
74
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Stat","StatSettings","Text","TextSettings","Table","TableSettings"],"sources":["../../src/widgets/index.ts"],"sourcesContent":["import { HashIcon, TableIcon, TypeIcon } from '@dou-ui/icons'\nimport { defineDashboardWidget } from '../widget/define'\nimport type { DashboardWidgetType } from '../widget/define'\nimport Stat from './stat.vue'\nimport StatSettings from './stat-settings.vue'\nimport Table from './table.vue'\nimport TableSettings from './table-settings.vue'\nimport Text from './text.vue'\nimport TextSettings from './text-settings.vue'\nimport type { StatWidgetProps, TableWidgetProps, TextWidgetProps } from './types'\n\nexport type { StatWidgetProps, TableWidgetColumn, TableWidgetProps, TextWidgetProps } from './types'\nexport { fieldsOf, filterValueOf, numberFieldsOf, rowsOf, valueAt } from './shared'\n\n/** What a built-in widget's definition can change: its type, label, icon, size and more. */\nexport type WidgetOverrides<P extends object> = Partial<Omit<DashboardWidgetType<P>, 'component'>>\n\n/**\n * A number, read from a source or given, with its change since the last\n * period and a sparkline under it.\n */\nexport function statWidget(overrides: WidgetOverrides<StatWidgetProps> = {}) {\n return defineDashboardWidget<StatWidgetProps>({\n type: 'stat',\n label: '统计数字',\n icon: HashIcon,\n size: { w: 3, h: 2, minW: 2, minH: 2 },\n defaultProps: { value: 0 },\n component: Stat,\n settings: StatSettings,\n fullscreen: false,\n ...overrides,\n })\n}\n\n/** A note: plain text in three sizes, its line breaks kept. */\nexport function textWidget(overrides: WidgetOverrides<TextWidgetProps> = {}) {\n return defineDashboardWidget<TextWidgetProps>({\n type: 'text',\n label: '文字',\n icon: TypeIcon,\n size: { w: 4, h: 2, minW: 2, minH: 1 },\n defaultProps: { text: '', size: 'md' },\n component: Text,\n settings: TextSettings,\n fullscreen: false,\n ...overrides,\n })\n}\n\n/** A source's rows in a table, with the columns picked in its settings. */\nexport function tableWidget(overrides: WidgetOverrides<TableWidgetProps> = {}) {\n return defineDashboardWidget<TableWidgetProps>({\n type: 'table',\n label: '表格',\n icon: TableIcon,\n size: { w: 6, h: 4, minW: 3, minH: 3 },\n component: Table,\n settings: TableSettings,\n ...overrides,\n })\n}\n"],"mappings":";;;;;;;;;;;;;;AAqBA,SAAgB,WAAW,YAA8C,CAAC,GAAG;CAC3E,OAAO,sBAAuC;EAC5C,MAAM;EACN,OAAO;EACP,MAAM;EACN,MAAM;GAAE,GAAG;GAAG,GAAG;GAAG,MAAM;GAAG,MAAM;EAAE;EACrC,cAAc,EAAE,OAAO,EAAE;EACzB,WAAWA;EACX,UAAUC;EACV,YAAY;EACZ,GAAG;CACL,CAAC;AACH;;AAGA,SAAgB,WAAW,YAA8C,CAAC,GAAG;CAC3E,OAAO,sBAAuC;EAC5C,MAAM;EACN,OAAO;EACP,MAAM;EACN,MAAM;GAAE,GAAG;GAAG,GAAG;GAAG,MAAM;GAAG,MAAM;EAAE;EACrC,cAAc;GAAE,MAAM;GAAI,MAAM;EAAK;EACrC,WAAWC;EACX,UAAUC;EACV,YAAY;EACZ,GAAG;CACL,CAAC;AACH;;AAGA,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,WAAWC;EACX,UAAUC;EACV,GAAG;CACL,CAAC;AACH"}
1
+ {"version":3,"file":"index.js","names":["Stat","StatSettings","Text","TextSettings","Table","TableSettings"],"sources":["../../src/widgets/index.ts"],"sourcesContent":["import { HashIcon, TableIcon, TypeIcon } from '@dou-ui/icons'\nimport { defineDashboardWidget } from '../widget/define'\nimport type { DashboardWidgetType } from '../widget/define'\nimport Stat from './stat.vue'\nimport StatSettings from './stat-settings.vue'\nimport Table from './table.vue'\nimport TableSettings from './table-settings.vue'\nimport Text from './text.vue'\nimport TextSettings from './text-settings.vue'\nimport type { StatWidgetProps, TableWidgetProps, TextWidgetProps } from './types'\n\nexport type { StatWidgetProps, TableWidgetColumn, TableWidgetProps, TextWidgetProps } from './types'\nexport {\n fieldsOf,\n filterValueOf,\n flagOf,\n numberFieldsOf,\n numberOf,\n recordOf,\n rowsOf,\n textOf,\n textsOf,\n valueAt,\n} from './shared'\n\n/** What a built-in widget's definition can change: its type, label, icon, size and more. */\nexport type WidgetOverrides<P extends object> = Partial<Omit<DashboardWidgetType<P>, 'component'>>\n\n/**\n * A number, read from a source or given, with its change since the last\n * period and a sparkline under it.\n */\nexport function statWidget(overrides: WidgetOverrides<StatWidgetProps> = {}) {\n return defineDashboardWidget<StatWidgetProps>({\n type: 'stat',\n label: '统计数字',\n icon: HashIcon,\n size: { w: 3, h: 2, minW: 2, minH: 2 },\n defaultProps: { value: 0 },\n component: Stat,\n settings: StatSettings,\n fullscreen: false,\n ...overrides,\n })\n}\n\n/** A note: plain text in three sizes, its line breaks kept. */\nexport function textWidget(overrides: WidgetOverrides<TextWidgetProps> = {}) {\n return defineDashboardWidget<TextWidgetProps>({\n type: 'text',\n label: '文字',\n icon: TypeIcon,\n size: { w: 4, h: 2, minW: 2, minH: 1 },\n defaultProps: { text: '', size: 'md' },\n component: Text,\n settings: TextSettings,\n fullscreen: false,\n ...overrides,\n })\n}\n\n/** A source's rows in a table, with the columns picked in its settings. */\nexport function tableWidget(overrides: WidgetOverrides<TableWidgetProps> = {}) {\n return defineDashboardWidget<TableWidgetProps>({\n type: 'table',\n label: '表格',\n icon: TableIcon,\n size: { w: 6, h: 4, minW: 3, minH: 3 },\n component: Table,\n settings: TableSettings,\n ...overrides,\n })\n}\n"],"mappings":";;;;;;;;;;;;;;AAgCA,SAAgB,WAAW,YAA8C,CAAC,GAAG;CAC3E,OAAO,sBAAuC;EAC5C,MAAM;EACN,OAAO;EACP,MAAM;EACN,MAAM;GAAE,GAAG;GAAG,GAAG;GAAG,MAAM;GAAG,MAAM;EAAE;EACrC,cAAc,EAAE,OAAO,EAAE;EACzB,WAAWA;EACX,UAAUC;EACV,YAAY;EACZ,GAAG;CACL,CAAC;AACH;;AAGA,SAAgB,WAAW,YAA8C,CAAC,GAAG;CAC3E,OAAO,sBAAuC;EAC5C,MAAM;EACN,OAAO;EACP,MAAM;EACN,MAAM;GAAE,GAAG;GAAG,GAAG;GAAG,MAAM;GAAG,MAAM;EAAE;EACrC,cAAc;GAAE,MAAM;GAAI,MAAM;EAAK;EACrC,WAAWC;EACX,UAAUC;EACV,YAAY;EACZ,GAAG;CACL,CAAC;AACH;;AAGA,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,WAAWC;EACX,UAAUC;EACV,GAAG;CACL,CAAC;AACH"}
@@ -0,0 +1,52 @@
1
+ import { numberOf, oneOf, recordOf, textOf } from "./shared.js";
2
+ // src/widgets/read-props.ts
3
+ function statPropsOf(props) {
4
+ const precision = numberOf(props.precision);
5
+ return {
6
+ source: textOf(props.source),
7
+ field: textOf(props.field),
8
+ value: numberOf(props.value),
9
+ prefix: textOf(props.prefix),
10
+ suffix: textOf(props.suffix),
11
+ precision: precision !== void 0 && Number.isInteger(precision) && precision >= 0 && precision <= 20 ? precision : void 0,
12
+ trend: textOf(props.trend),
13
+ delta: textOf(props.delta)
14
+ };
15
+ }
16
+ function textPropsOf(props) {
17
+ const text = props.text;
18
+ return {
19
+ text: typeof text === "number" ? String(text) : textOf(text),
20
+ size: oneOf(props.size, [
21
+ "sm",
22
+ "md",
23
+ "lg"
24
+ ])
25
+ };
26
+ }
27
+ /** The columns given, those with a text `key`; not set when not a list. */
28
+ function columnsOf(value) {
29
+ if (!Array.isArray(value)) return void 0;
30
+ const columns = [];
31
+ for (const item of value) {
32
+ const column = recordOf(item);
33
+ if (typeof column?.key !== "string") continue;
34
+ const title = textOf(column.title);
35
+ columns.push(title === void 0 ? { key: column.key } : {
36
+ key: column.key,
37
+ title
38
+ });
39
+ }
40
+ return columns;
41
+ }
42
+ function tablePropsOf(props) {
43
+ return {
44
+ source: textOf(props.source),
45
+ path: textOf(props.path),
46
+ columns: columnsOf(props.columns),
47
+ rowKey: textOf(props.rowKey)
48
+ };
49
+ }
50
+ export { statPropsOf, tablePropsOf, textPropsOf };
51
+
52
+ //# sourceMappingURL=read-props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-props.js","names":[],"sources":["../../src/widgets/read-props.ts"],"sourcesContent":["import { numberOf, oneOf, recordOf, textOf } from './shared'\nimport type { StatWidgetProps, TableWidgetColumn, TableWidgetProps, TextWidgetProps } from './types'\n\n/*\n * The props of the built-in widgets as their types say, from whatever JSON\n * was saved: what isn't the right type counts as not set. The widgets and\n * their settings both read through these.\n */\n\nexport function statPropsOf(props: Record<string, unknown>): StatWidgetProps {\n const precision = numberOf(props.precision)\n return {\n source: textOf(props.source),\n field: textOf(props.field),\n value: numberOf(props.value),\n prefix: textOf(props.prefix),\n suffix: textOf(props.suffix),\n precision:\n precision !== undefined && Number.isInteger(precision) && precision >= 0 && precision <= 20\n ? precision\n : undefined,\n trend: textOf(props.trend),\n delta: textOf(props.delta),\n }\n}\n\nexport function textPropsOf(props: Record<string, unknown>): TextWidgetProps {\n const text = props.text\n return {\n text: typeof text === 'number' ? String(text) : textOf(text),\n size: oneOf(props.size, ['sm', 'md', 'lg'] as const),\n }\n}\n\n/** The columns given, those with a text `key`; not set when not a list. */\nfunction columnsOf(value: unknown): TableWidgetColumn[] | undefined {\n if (!Array.isArray(value)) return undefined\n const columns: TableWidgetColumn[] = []\n for (const item of value) {\n const column = recordOf(item)\n if (typeof column?.key !== 'string') continue\n const title = textOf(column.title)\n columns.push(title === undefined ? { key: column.key } : { key: column.key, title })\n }\n return columns\n}\n\nexport function tablePropsOf(props: Record<string, unknown>): TableWidgetProps {\n return {\n source: textOf(props.source),\n path: textOf(props.path),\n columns: columnsOf(props.columns),\n rowKey: textOf(props.rowKey),\n }\n}\n"],"mappings":";;AASA,SAAgB,YAAY,OAAiD;CAC3E,MAAM,YAAY,SAAS,MAAM,SAAS;CAC1C,OAAO;EACL,QAAQ,OAAO,MAAM,MAAM;EAC3B,OAAO,OAAO,MAAM,KAAK;EACzB,OAAO,SAAS,MAAM,KAAK;EAC3B,QAAQ,OAAO,MAAM,MAAM;EAC3B,QAAQ,OAAO,MAAM,MAAM;EAC3B,WACE,cAAc,KAAA,KAAa,OAAO,UAAU,SAAS,KAAK,aAAa,KAAK,aAAa,KACrF,YACA,KAAA;EACN,OAAO,OAAO,MAAM,KAAK;EACzB,OAAO,OAAO,MAAM,KAAK;CAC3B;AACF;AAEA,SAAgB,YAAY,OAAiD;CAC3E,MAAM,OAAO,MAAM;CACnB,OAAO;EACL,MAAM,OAAO,SAAS,WAAW,OAAO,IAAI,IAAI,OAAO,IAAI;EAC3D,MAAM,MAAM,MAAM,MAAM;GAAC;GAAM;GAAM;EAAI,CAAU;CACrD;AACF;;AAGA,SAAS,UAAU,OAAiD;CAClE,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,KAAA;CAClC,MAAM,UAA+B,CAAC;CACtC,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,SAAS,SAAS,IAAI;EAC5B,IAAI,OAAO,QAAQ,QAAQ,UAAU;EACrC,MAAM,QAAQ,OAAO,OAAO,KAAK;EACjC,QAAQ,KAAK,UAAU,KAAA,IAAY,EAAE,KAAK,OAAO,IAAI,IAAI;GAAE,KAAK,OAAO;GAAK;EAAM,CAAC;CACrF;CACA,OAAO;AACT;AAEA,SAAgB,aAAa,OAAkD;CAC7E,OAAO;EACL,QAAQ,OAAO,MAAM,MAAM;EAC3B,MAAM,OAAO,MAAM,IAAI;EACvB,SAAS,UAAU,MAAM,OAAO;EAChC,QAAQ,OAAO,MAAM,MAAM;CAC7B;AACF"}
@@ -1,7 +1,12 @@
1
1
  // src/widgets/shared.ts
2
- /** The value at a dotted path, e.g. `total.amount`; the data itself for an empty path. */
2
+ /**
3
+ * The value at a dotted path, e.g. `total.amount`; the data itself for an
4
+ * empty path. A path that isn't text, e.g. a number in JSON written by hand
5
+ * or by a program, finds nothing.
6
+ */
3
7
  function valueAt(data, path) {
4
- if (!path) return data;
8
+ if (path === void 0 || path === null || path === "") return data;
9
+ if (typeof path !== "string") return void 0;
5
10
  let value = data;
6
11
  for (const key of path.split(".")) {
7
12
  if (value == null || typeof value !== "object") return void 0;
@@ -9,11 +14,28 @@ function valueAt(data, path) {
9
14
  }
10
15
  return value;
11
16
  }
12
- /** The rows of a source's data: the data when it is a list, or the list at `path`. */
17
+ /** The rows of a source's data: the data when it is a list, or the list at `path`. Items that aren't objects are left out. */
13
18
  function rowsOf(data, path) {
14
19
  const value = valueAt(data, path);
15
- return Array.isArray(value) ? value : [];
20
+ if (!Array.isArray(value)) return [];
21
+ return value.every(isRecord) ? value : value.filter(isRecord);
22
+ }
23
+ var isRecord = (value) => value !== null && typeof value === "object";
24
+ /** Text, or not set. */
25
+ var textOf = (value) => typeof value === "string" ? value : void 0;
26
+ /** A list of texts: the texts in it, or none. */
27
+ var textsOf = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
28
+ /** A finite number, or text that is one (`'12'`, as a number read from data); otherwise not set. */
29
+ function numberOf(value) {
30
+ const n = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : NaN;
31
+ return Number.isFinite(n) ? n : void 0;
16
32
  }
33
+ /** On only for `true`: `'no'` or `1` don't turn a switch on. */
34
+ var flagOf = (value) => value === true;
35
+ /** A plain object, not a list; otherwise not set. */
36
+ var recordOf = (value) => isRecord(value) && !Array.isArray(value) ? value : void 0;
37
+ /** One of the values listed, or not set. */
38
+ var oneOf = (value, values) => values.includes(value) ? value : void 0;
17
39
  /** The keys of the first row of a list, or of an object: the fields to pick from in settings. */
18
40
  function fieldsOf(data) {
19
41
  const first = Array.isArray(data) ? data[0] : data;
@@ -63,6 +85,6 @@ function rowsToWorkbook(name, columns, rows) {
63
85
  styles: { head: { bold: true } }
64
86
  };
65
87
  }
66
- export { fieldsOf, filterValueOf, numberFieldsOf, rowsOf, rowsToWorkbook, valueAt };
88
+ export { fieldsOf, filterValueOf, flagOf, numberFieldsOf, numberOf, oneOf, recordOf, rowsOf, rowsToWorkbook, textOf, textsOf, valueAt };
67
89
 
68
90
  //# sourceMappingURL=shared.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"shared.js","names":[],"sources":["../../src/widgets/shared.ts"],"sourcesContent":["import type { SheetValue, SheetWorkbook } from '@dou-ui/sheet/core'\n\n/**\n * The value at a dotted path, e.g. `total.amount`; the data itself for an\n * empty path. A path that isn't text, e.g. a number in JSON written by hand\n * or by a program, finds nothing.\n */\nexport function valueAt(data: unknown, path: unknown): unknown {\n if (path === undefined || path === null || path === '') return data\n if (typeof path !== 'string') return undefined\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`. Items that aren't objects are left out. */\nexport function rowsOf(data: unknown, path?: unknown): Record<string, unknown>[] {\n const value = valueAt(data, path)\n if (!Array.isArray(value)) return []\n return value.every(isRecord) ? value : value.filter(isRecord)\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === 'object'\n\n/*\n * A widget's props come from JSON that types don't check, often written by a\n * program or an AI. These read one prop as the type it is meant to be; any\n * other value counts as not set, so a widget never throws on it.\n */\n\n/** Text, or not set. */\nexport const textOf = (value: unknown): string | undefined =>\n typeof value === 'string' ? value : undefined\n\n/** A list of texts: the texts in it, or none. */\nexport const textsOf = (value: unknown): string[] =>\n Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : []\n\n/** A finite number, or text that is one (`'12'`, as a number read from data); otherwise not set. */\nexport function numberOf(value: unknown): number | undefined {\n const n =\n typeof value === 'number'\n ? value\n : typeof value === 'string' && value.trim()\n ? Number(value)\n : Number.NaN\n return Number.isFinite(n) ? n : undefined\n}\n\n/** On only for `true`: `'no'` or `1` don't turn a switch on. */\nexport const flagOf = (value: unknown): boolean => value === true\n\n/** A plain object, not a list; otherwise not set. */\nexport const recordOf = (value: unknown): Record<string, unknown> | undefined =>\n isRecord(value) && !Array.isArray(value) ? value : undefined\n\n/** One of the values listed, or not set. */\nexport const oneOf = <T extends string>(value: unknown, values: readonly T[]): T | undefined =>\n values.includes(value as T) ? (value as T) : undefined\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":";;;;;;AAOA,SAAgB,QAAQ,MAAe,MAAwB;CAC7D,IAAI,SAAS,KAAA,KAAa,SAAS,QAAQ,SAAS,IAAI,OAAO;CAC/D,IAAI,OAAO,SAAS,UAAU,OAAO,KAAA;CACrC,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,MAA2C;CAC/E,MAAM,QAAQ,QAAQ,MAAM,IAAI;CAChC,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACnC,OAAO,MAAM,MAAM,QAAQ,IAAI,QAAQ,MAAM,OAAO,QAAQ;AAC9D;AAEA,IAAM,YAAY,UAChB,UAAU,QAAQ,OAAO,UAAU;;AASrC,IAAa,UAAU,UACrB,OAAO,UAAU,WAAW,QAAQ,KAAA;;AAGtC,IAAa,WAAW,UACtB,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,SAAyB,OAAO,SAAS,QAAQ,IAAI,CAAC;;AAG7F,SAAgB,SAAS,OAAoC;CAC3D,MAAM,IACJ,OAAO,UAAU,WACb,QACA,OAAO,UAAU,YAAY,MAAM,KAAK,IACtC,OAAO,KAAK,IACZ;CACR,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,KAAA;AAClC;;AAGA,IAAa,UAAU,UAA4B,UAAU;;AAG7D,IAAa,YAAY,UACvB,SAAS,KAAK,KAAK,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAQ,KAAA;;AAGrD,IAAa,SAA2B,OAAgB,WACtD,OAAO,SAAS,KAAU,IAAK,QAAc,KAAA;;AAG/C,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"}
@@ -1 +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":""}
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'\nimport { statPropsOf } from './read-props'\n\ndefineOptions({ name: 'DouDashboardStatSettings' })\n\nconst model = defineModel<StatWidgetProps>({ required: true })\n// the props as saved may have the wrong types: read them as the widget does\nconst view = computed(() => statPropsOf(model.value as Record<string, unknown>))\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=\"view.source\"\n optional\n @update:model-value=\"(source) => set({ source })\"\n />\n <FieldSelect\n v-if=\"view.source\"\n :model-value=\"view.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=\"view.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=\"view.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=\"view.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=\"view.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=\"view.source\">\n <FieldSelect\n :model-value=\"view.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=\"view.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":""}
@@ -1,6 +1,7 @@
1
1
  import { useDashboardMessages } from "../locale.js";
2
2
  import { useDashboardWidget } from "../widget/context.js";
3
3
  import { fieldsOf } from "./shared.js";
4
+ import { statPropsOf } from "./read-props.js";
4
5
  import settings_field_default from "./settings-field.js";
5
6
  import field_select_default from "./field-select.js";
6
7
  import source_field_default from "./source-field.js";
@@ -19,6 +20,7 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
19
20
  emits: ["update:modelValue"],
20
21
  setup(__props) {
21
22
  const model = useModel(__props, "modelValue");
23
+ const view = computed(() => statPropsOf(model.value));
22
24
  const messages = useDashboardMessages();
23
25
  const { data } = useDashboardWidget();
24
26
  const fields = computed(() => fieldsOf(data.value));
@@ -29,13 +31,13 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
29
31
  return (_ctx, _cache) => {
30
32
  return openBlock(), createElementBlock("div", _hoisted_1, [
31
33
  createVNode(source_field_default, {
32
- "model-value": model.value.source,
34
+ "model-value": view.value.source,
33
35
  optional: "",
34
36
  "onUpdate:modelValue": _cache[0] || (_cache[0] = (source) => set({ source }))
35
37
  }, null, 8, ["model-value"]),
36
- model.value.source ? (openBlock(), createBlock(field_select_default, {
38
+ view.value.source ? (openBlock(), createBlock(field_select_default, {
37
39
  key: 0,
38
- "model-value": model.value.field,
40
+ "model-value": view.value.field,
39
41
  label: unref(messages).value,
40
42
  fields: fields.value,
41
43
  "onUpdate:modelValue": _cache[1] || (_cache[1] = (field) => set({ field }))
@@ -48,7 +50,7 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
48
50
  label: unref(messages).value
49
51
  }, {
50
52
  default: withCtx(() => [createVNode(unref(DouInputNumber), {
51
- "model-value": model.value.value ?? null,
53
+ "model-value": view.value.value ?? null,
52
54
  "aria-label": unref(messages).value,
53
55
  "onUpdate:modelValue": _cache[2] || (_cache[2] = (value) => set({ value: value ?? void 0 }))
54
56
  }, null, 8, ["model-value", "aria-label"])]),
@@ -56,14 +58,14 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
56
58
  }, 8, ["label"])),
57
59
  createElementVNode("div", _hoisted_2, [createVNode(settings_field_default, { label: unref(messages).prefix }, {
58
60
  default: withCtx(() => [createVNode(unref(DouInput), {
59
- "model-value": model.value.prefix ?? "",
61
+ "model-value": view.value.prefix ?? "",
60
62
  "aria-label": unref(messages).prefix,
61
63
  "onUpdate:modelValue": _cache[3] || (_cache[3] = (prefix) => set({ prefix: prefix || void 0 }))
62
64
  }, null, 8, ["model-value", "aria-label"])]),
63
65
  _: 1
64
66
  }, 8, ["label"]), createVNode(settings_field_default, { label: unref(messages).suffix }, {
65
67
  default: withCtx(() => [createVNode(unref(DouInput), {
66
- "model-value": model.value.suffix ?? "",
68
+ "model-value": view.value.suffix ?? "",
67
69
  "aria-label": unref(messages).suffix,
68
70
  "onUpdate:modelValue": _cache[4] || (_cache[4] = (suffix) => set({ suffix: suffix || void 0 }))
69
71
  }, null, 8, ["model-value", "aria-label"])]),
@@ -71,7 +73,7 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
71
73
  }, 8, ["label"])]),
72
74
  createVNode(settings_field_default, { label: unref(messages).precision }, {
73
75
  default: withCtx(() => [createVNode(unref(DouInputNumber), {
74
- "model-value": model.value.precision ?? null,
76
+ "model-value": view.value.precision ?? null,
75
77
  min: 0,
76
78
  max: 6,
77
79
  "aria-label": unref(messages).precision,
@@ -79,8 +81,8 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
79
81
  }, null, 8, ["model-value", "aria-label"])]),
80
82
  _: 1
81
83
  }, 8, ["label"]),
82
- model.value.source ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(field_select_default, {
83
- "model-value": model.value.trend,
84
+ view.value.source ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(field_select_default, {
85
+ "model-value": view.value.trend,
84
86
  label: unref(messages).trend,
85
87
  fields: fields.value,
86
88
  "onUpdate:modelValue": _cache[6] || (_cache[6] = (trend) => set({ trend }))
@@ -89,7 +91,7 @@ var stat_settings_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
89
91
  "label",
90
92
  "fields"
91
93
  ]), createVNode(field_select_default, {
92
- "model-value": model.value.delta,
94
+ "model-value": view.value.delta,
93
95
  label: unref(messages).delta,
94
96
  fields: fields.value,
95
97
  "onUpdate:modelValue": _cache[7] || (_cache[7] = (delta) => set({ delta }))