@c2-markdown-ui/react 0.4.4 → 0.4.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 (73) hide show
  1. package/README.md +24 -6
  2. package/dist/index.js +4365 -3733
  3. package/package.json +2 -2
  4. package/src/lib/MarkdownUI.tsx +47 -9
  5. package/src/lib/widgets.css +2188 -1372
  6. package/src/widgets/Button.tsx +39 -39
  7. package/src/widgets/ButtonGroup.tsx +47 -47
  8. package/src/widgets/Cascader.tsx +3 -2
  9. package/src/widgets/Chart.tsx +237 -237
  10. package/src/widgets/DatePicker.tsx +451 -434
  11. package/src/widgets/Form.tsx +512 -372
  12. package/src/widgets/Incomplete.tsx +3 -3
  13. package/src/widgets/MultipleChoiceQuestion.tsx +82 -82
  14. package/src/widgets/Quiz.tsx +320 -320
  15. package/src/widgets/Radio.tsx +57 -26
  16. package/src/widgets/Select.tsx +178 -142
  17. package/src/widgets/SelectMulti.tsx +105 -72
  18. package/src/widgets/ShortAnswerQuestion.tsx +101 -101
  19. package/src/widgets/Slider.tsx +70 -56
  20. package/src/widgets/Switch.tsx +14 -2
  21. package/src/widgets/TextInput.tsx +76 -38
  22. package/src/widgets/TreeSelect.tsx +649 -0
  23. package/src/widgets/Widget.tsx +130 -82
  24. package/src/widgets/choiceUtils.ts +90 -45
  25. package/src/widgets/index.ts +17 -16
  26. package/dist/index.d.ts +0 -2
  27. package/dist/index.d.ts.map +0 -1
  28. package/dist/lib/MarkdownUI.d.ts +0 -10
  29. package/dist/lib/MarkdownUI.d.ts.map +0 -1
  30. package/dist/lib/index.d.ts +0 -4
  31. package/dist/lib/index.d.ts.map +0 -1
  32. package/dist/widgets/Button.d.ts +0 -15
  33. package/dist/widgets/Button.d.ts.map +0 -1
  34. package/dist/widgets/ButtonGroup.d.ts +0 -11
  35. package/dist/widgets/ButtonGroup.d.ts.map +0 -1
  36. package/dist/widgets/Cascader.d.ts +0 -34
  37. package/dist/widgets/Cascader.d.ts.map +0 -1
  38. package/dist/widgets/Chart.d.ts +0 -20
  39. package/dist/widgets/Chart.d.ts.map +0 -1
  40. package/dist/widgets/DatePicker.d.ts +0 -28
  41. package/dist/widgets/DatePicker.d.ts.map +0 -1
  42. package/dist/widgets/Form.d.ts +0 -47
  43. package/dist/widgets/Form.d.ts.map +0 -1
  44. package/dist/widgets/Incomplete.d.ts +0 -3
  45. package/dist/widgets/Incomplete.d.ts.map +0 -1
  46. package/dist/widgets/MultipleChoiceQuestion.d.ts +0 -15
  47. package/dist/widgets/MultipleChoiceQuestion.d.ts.map +0 -1
  48. package/dist/widgets/NumberInput.d.ts +0 -26
  49. package/dist/widgets/NumberInput.d.ts.map +0 -1
  50. package/dist/widgets/Quiz.d.ts +0 -37
  51. package/dist/widgets/Quiz.d.ts.map +0 -1
  52. package/dist/widgets/Radio.d.ts +0 -24
  53. package/dist/widgets/Radio.d.ts.map +0 -1
  54. package/dist/widgets/Select.d.ts +0 -15
  55. package/dist/widgets/Select.d.ts.map +0 -1
  56. package/dist/widgets/SelectMulti.d.ts +0 -20
  57. package/dist/widgets/SelectMulti.d.ts.map +0 -1
  58. package/dist/widgets/ShortAnswerQuestion.d.ts +0 -16
  59. package/dist/widgets/ShortAnswerQuestion.d.ts.map +0 -1
  60. package/dist/widgets/Slider.d.ts +0 -13
  61. package/dist/widgets/Slider.d.ts.map +0 -1
  62. package/dist/widgets/Switch.d.ts +0 -17
  63. package/dist/widgets/Switch.d.ts.map +0 -1
  64. package/dist/widgets/TextInput.d.ts +0 -11
  65. package/dist/widgets/TextInput.d.ts.map +0 -1
  66. package/dist/widgets/Widget.d.ts +0 -7
  67. package/dist/widgets/Widget.d.ts.map +0 -1
  68. package/dist/widgets/chartRemoteData.d.ts +0 -18
  69. package/dist/widgets/chartRemoteData.d.ts.map +0 -1
  70. package/dist/widgets/choiceUtils.d.ts +0 -24
  71. package/dist/widgets/choiceUtils.d.ts.map +0 -1
  72. package/dist/widgets/index.d.ts +0 -18
  73. package/dist/widgets/index.d.ts.map +0 -1
@@ -1,83 +1,131 @@
1
- import React, { useEffect } from 'react';
2
- import * as widgets from './index';
3
-
4
- export interface WidgetProps {
5
- id: string;
6
- content: string;
7
- }
8
-
9
- type WidgetType = keyof typeof widgets;
10
-
11
- // Map camelCase JSON types to PascalCase component names
12
- const typeMapping: Record<string, WidgetType> = {
13
- 'button': 'Button',
14
- 'button-group': 'ButtonGroup',
15
- 'cascade': 'Cascader',
16
- 'chart-line': 'Chart',
17
- 'chart-bar': 'Chart',
18
- 'chart-pie': 'Chart',
19
- 'chart-scatter': 'Chart',
20
- 'date-picker': 'DatePicker',
21
- 'form': 'Form',
22
- 'incomplete': 'Incomplete',
23
- 'multiple-choice-question': 'MultipleChoiceQuestion',
24
- 'number-input': 'NumberInput',
25
- 'quiz': 'Quiz',
26
- 'radio-group': 'RadioGroup',
27
- 'select': 'Select',
28
- 'select-multi': 'SelectMulti',
29
- 'short-answer-question': 'ShortAnswerQuestion',
30
- 'slider': 'Slider',
31
- 'switch': 'Switch',
32
- 'text-input': 'TextInput'
33
- };
34
-
35
- export const Widget: React.FC<WidgetProps> = ({ id, content }) => {
36
- const parsed = JSON.parse(decodeURIComponent(content));
37
- const componentType = typeMapping[parsed.type] || parsed.type;
38
- const WidgetComponent = widgets[componentType as WidgetType];
39
-
40
- const dispatch = (detail: any) => {
41
- console.log('🔥 Widget dispatch called', { id, detail });
42
-
43
- const event = new CustomEvent('widget-event', {
44
- detail: detail,
45
- bubbles: true,
46
- composed: true
47
- });
48
-
49
- // Find the custom element and bubble up to find the closest widget container
50
- const customElement = document.querySelector(`markdown-ui-widget[id="${id}"]`);
51
- console.log('🔍 Custom element found:', customElement);
52
-
53
- if (customElement) {
54
- const container = customElement.closest('.widget-container');
55
- console.log('📦 Container found:', container);
56
- if (container) {
57
- console.log('📤 Dispatching event on container');
58
- container.dispatchEvent(event);
59
- }
60
- } else {
61
- console.log('❌ No custom element found for id:', id);
62
- }
63
- };
64
-
65
- if (!WidgetComponent) {
66
- return (
67
- <div className="widget">
68
- <span style={{ color: 'red' }}>
69
- Unknown widget "{parsed.type}"
70
- </span>
71
- </div>
72
- );
73
- }
74
-
75
- return (
76
- <div className="widget">
77
- <WidgetComponent
78
- {...parsed}
79
- onchange={(value: any) => dispatch({ id, value })}
80
- />
81
- </div>
82
- );
1
+ import React, { useEffect } from 'react';
2
+ import * as widgets from './index';
3
+
4
+ export interface WidgetProps {
5
+ id: string;
6
+ content: string;
7
+ /** 外部传入的表单初始值(encodeURIComponent 后的 JSON 字符串),由 MarkdownUI 注入 */
8
+ data?: string;
9
+ }
10
+
11
+ type WidgetType = keyof typeof widgets;
12
+
13
+ // Map camelCase JSON types to PascalCase component names
14
+ const typeMapping: Record<string, WidgetType> = {
15
+ 'button': 'Button',
16
+ 'button-group': 'ButtonGroup',
17
+ 'cascade': 'Cascader',
18
+ 'chart-line': 'Chart',
19
+ 'chart-bar': 'Chart',
20
+ 'chart-pie': 'Chart',
21
+ 'chart-scatter': 'Chart',
22
+ 'date-picker': 'DatePicker',
23
+ 'form': 'Form',
24
+ 'incomplete': 'Incomplete',
25
+ 'multiple-choice-question': 'MultipleChoiceQuestion',
26
+ 'number-input': 'NumberInput',
27
+ 'quiz': 'Quiz',
28
+ 'radio-group': 'RadioGroup',
29
+ 'select': 'Select',
30
+ 'select-multi': 'SelectMulti',
31
+ 'tree-select': 'TreeSelect',
32
+ 'short-answer-question': 'ShortAnswerQuestion',
33
+ 'slider': 'Slider',
34
+ 'switch': 'Switch',
35
+ 'text-input': 'TextInput'
36
+ };
37
+
38
+ export const Widget: React.FC<WidgetProps> = ({ id, content, data }) => {
39
+ const parsed = JSON.parse(decodeURIComponent(content));
40
+ const componentType = typeMapping[parsed.type] || parsed.type;
41
+ const WidgetComponent = widgets[componentType as WidgetType];
42
+
43
+ // 解析外部注入的表单初始值(容错:非法 JSON 时忽略)
44
+ let initialData: Record<string, unknown> | undefined;
45
+ if (data) {
46
+ try {
47
+ initialData = JSON.parse(decodeURIComponent(data));
48
+ } catch {
49
+ initialData = undefined;
50
+ }
51
+ }
52
+
53
+ const dispatch = (detail: any) => {
54
+ console.log('🔥 Widget dispatch called', { id, detail });
55
+
56
+ const event = new CustomEvent('widget-event', {
57
+ detail: detail,
58
+ bubbles: true,
59
+ composed: true
60
+ });
61
+
62
+ // Find the custom element and bubble up to find the closest widget container
63
+ const customElement = document.querySelector(`markdown-ui-widget[id="${id}"]`);
64
+ console.log('🔍 Custom element found:', customElement);
65
+
66
+ if (customElement) {
67
+ const container = customElement.closest('.widget-container');
68
+ console.log('📦 Container found:', container);
69
+ if (container) {
70
+ console.log('📤 Dispatching event on container');
71
+ container.dispatchEvent(event);
72
+ }
73
+ } else {
74
+ console.log('❌ No custom element found for id:', id);
75
+ }
76
+ };
77
+
78
+ /** form 提交事件:独立于 widget-event,通过 widget-submit 派发 */
79
+ const dispatchSubmit = (value: any) => {
80
+ const customElement = document.querySelector(`markdown-ui-widget[id="${id}"]`);
81
+ if (customElement) {
82
+ const container = customElement.closest('.widget-container');
83
+ if (container) {
84
+ container.dispatchEvent(new CustomEvent('widget-submit', {
85
+ detail: { id, value },
86
+ bubbles: true,
87
+ composed: true
88
+ }));
89
+ }
90
+ }
91
+ };
92
+
93
+ /** form 字段级统计事件:任一表单项被填写时通过 widget-form-change 派发 */
94
+ const dispatchFieldChange = (stats: any) => {
95
+ const customElement = document.querySelector(`markdown-ui-widget[id="${id}"]`);
96
+ if (customElement) {
97
+ const container = customElement.closest('.widget-container');
98
+ if (container) {
99
+ container.dispatchEvent(new CustomEvent('widget-form-change', {
100
+ detail: { id, stats },
101
+ bubbles: true,
102
+ composed: true
103
+ }));
104
+ }
105
+ }
106
+ };
107
+
108
+ if (!WidgetComponent) {
109
+ return (
110
+ <div className="widget">
111
+ <span style={{ color: 'red' }}>
112
+ Unknown widget "{parsed.type}"
113
+ </span>
114
+ </div>
115
+ );
116
+ }
117
+
118
+ return (
119
+ <div className="widget">
120
+ <WidgetComponent
121
+ {...parsed}
122
+ initialData={initialData}
123
+ onchange={(value: any) => dispatch({ id, value })}
124
+ {...(parsed.type === 'form' ? {
125
+ onsubmit: (values: any) => dispatchSubmit(values),
126
+ onfieldchange: (stats: any) => dispatchFieldChange(stats)
127
+ } : {})}
128
+ />
129
+ </div>
130
+ );
83
131
  };
@@ -1,45 +1,90 @@
1
- /** 选项条目:value 是表单实际取值(key),label 是展示文案 */
2
- export interface ChoiceItem {
3
- value: string;
4
- label: string;
5
- }
6
-
7
- /**
8
- * 解析本地 choices 条目的 key:label 格式:
9
- * - "bj:北京" → {value: "bj", label: "北京"}(value 是表单实际取值,label 是展示文案)
10
- * - "北京" → {value: "北京", label: "北京"}(无冒号或不符合判定规则时视为纯文本)
11
- * - "09:00" → {value: "09:00", label: "09:00"}(纯数字 key 视为时间/比例值,保持原样)
12
- * - "http://x" → 原样(label 以 // 开头视为 URL)
13
- *
14
- * 判定规则:按首个冒号分割,仅当 key 非空且不含空白、非纯数字,
15
- * 且 label 非空、不以 // 开头时才视为 key:label。
16
- */
17
- export function parseChoice(c: string): ChoiceItem {
18
- const s = String(c ?? '');
19
- const idx = s.indexOf(':');
20
- if (idx > 0) {
21
- const key = s.slice(0, idx);
22
- const label = s.slice(idx + 1);
23
- if (key && label && !/\s/.test(key) && !/^\d+$/.test(key) && !label.startsWith('//')) {
24
- return { value: key, label };
25
- }
26
- }
27
- return { value: s, label: s };
28
- }
29
-
30
- /** 把本地 choices(string[] 或对象数组)解析为 {value,label} 数组。
31
- * 对象条目:value > key 取值(表单实际取值),label 缺省回落到 value */
32
- export function parseChoices(choices: string[] | Array<{ value?: string; key?: string; label?: string }> | undefined | null): ChoiceItem[] {
33
- return (choices || []).map((c) => {
34
- if (c !== null && typeof c === 'object') {
35
- const value = (c as any).value ?? (c as any).key;
36
- if (value === undefined || value === null || value === '') return null;
37
- const valueStr = String(value);
38
- const label = (c as any).label !== undefined && (c as any).label !== null && (c as any).label !== ''
39
- ? String((c as any).label)
40
- : valueStr;
41
- return { value: valueStr, label };
42
- }
43
- return parseChoice(c as string);
44
- }).filter((c: ChoiceItem | null): c is ChoiceItem => c !== null);
45
- }
1
+ /** 选项条目:value 是表单实际取值(key),label 是展示文案 */
2
+ export interface ChoiceItem {
3
+ value: string;
4
+ label: string;
5
+ }
6
+
7
+ /**
8
+ * 解析本地 choices 条目的 key:label 格式:
9
+ * - "bj:北京" → {value: "bj", label: "北京"}(value 是表单实际取值,label 是展示文案)
10
+ * - "北京" → {value: "北京", label: "北京"}(无冒号或不符合判定规则时视为纯文本)
11
+ * - "09:00" → {value: "09:00", label: "09:00"}(纯数字 key 视为时间/比例值,保持原样)
12
+ * - "http://x" → 原样(label 以 // 开头视为 URL)
13
+ *
14
+ * 判定规则:按首个冒号分割,仅当 key 非空且不含空白、非纯数字,
15
+ * 且 label 非空、不以 // 开头时才视为 key:label。
16
+ */
17
+ export function parseChoice(c: string): ChoiceItem {
18
+ const s = String(c ?? '');
19
+ const idx = s.indexOf(':');
20
+ if (idx > 0) {
21
+ const key = s.slice(0, idx);
22
+ const label = s.slice(idx + 1);
23
+ if (key && label && !/\s/.test(key) && !/^\d+$/.test(key) && !label.startsWith('//')) {
24
+ return { value: key, label };
25
+ }
26
+ }
27
+ return { value: s, label: s };
28
+ }
29
+
30
+ /** 把本地 choices(string[] 或对象数组)解析为 {value,label} 数组。
31
+ * 对象条目:value > key 取值(表单实际取值),label 缺省回落到 value */
32
+ export function parseChoices(choices: string[] | Array<{ value?: string; key?: string; label?: string }> | undefined | null): ChoiceItem[] {
33
+ return (choices || []).map((c) => {
34
+ if (c !== null && typeof c === 'object') {
35
+ const value = (c as any).value ?? (c as any).key;
36
+ if (value === undefined || value === null || value === '') return null;
37
+ const valueStr = String(value);
38
+ const label = (c as any).label !== undefined && (c as any).label !== null && (c as any).label !== ''
39
+ ? String((c as any).label)
40
+ : valueStr;
41
+ return { value: valueStr, label };
42
+ }
43
+ return parseChoice(c as string);
44
+ }).filter((c: ChoiceItem | null): c is ChoiceItem => c !== null);
45
+ }
46
+
47
+ /**
48
+ * 兼容常见远端响应格式并归一化为 {value,label}:
49
+ * - ["测试"] → value=label="测试"
50
+ * - [{key:"test",label:"测试"}] → value="test"(表单取值),label="测试"(展示)
51
+ * - [{value:"test",label:"测试"}] → value="test",label="测试"
52
+ * - {data:[...]} / {options:[...]} / {choices:[...]} / {items:[...]} → 取内嵌数组
53
+ *
54
+ * 对象条目取值优先级:value > key > id > name;展示优先级:label > name > text > value。
55
+ */
56
+ export function normalizeRemoteChoices(json: any): ChoiceItem[] {
57
+ let list = json;
58
+ if (!Array.isArray(json)) {
59
+ list = Array.isArray(json?.data) ? json.data
60
+ : Array.isArray(json?.options) ? json.options
61
+ : Array.isArray(json?.choices) ? json.choices
62
+ : Array.isArray(json?.items) ? json.items
63
+ : [];
64
+ }
65
+ return (list || [])
66
+ .map((item: any): ChoiceItem | null => {
67
+ if (typeof item === 'string' || typeof item === 'number') {
68
+ const s = String(item);
69
+ return s ? { value: s, label: s } : null;
70
+ }
71
+ if (item && typeof item === 'object') {
72
+ const value = item.value ?? item.key ?? item.id ?? item.name;
73
+ if (value === undefined || value === null || value === '') return null;
74
+ const label = item.label ?? item.name ?? item.text ?? String(value);
75
+ return { value: String(value), label: String(label) };
76
+ }
77
+ return null;
78
+ })
79
+ .filter((c: ChoiceItem | null): c is ChoiceItem => c !== null);
80
+ }
81
+
82
+ /**
83
+ * 把本地 choices / default 值(可能写的是展示文案或 key:label 原文)映射到远端 value 体系:
84
+ * 条目本身已是 value 优先,字符串则用 label 匹配远端条目回查 value。
85
+ */
86
+ export function resolveChoiceValue(c: string, remote: ChoiceItem[]): string {
87
+ const parsed = parseChoice(c).value;
88
+ const hit = remote.find(r => r.value === c || r.label === c || r.value === parsed);
89
+ return hit ? hit.value : c;
90
+ }
@@ -1,17 +1,18 @@
1
- export { Button } from './Button';
2
- export { ButtonGroup } from './ButtonGroup';
3
- export { Cascader } from './Cascader';
4
- export { Chart } from './Chart';
5
- export { DatePicker } from './DatePicker';
6
- export { Form } from './Form';
7
- export { Incomplete } from './Incomplete';
8
- export { MultipleChoiceQuestion } from './MultipleChoiceQuestion';
9
- export { NumberInput } from './NumberInput';
10
- export { Quiz } from './Quiz';
11
- export { RadioGroup } from './Radio';
12
- export { Select } from './Select';
13
- export { SelectMulti } from './SelectMulti';
14
- export { ShortAnswerQuestion } from './ShortAnswerQuestion';
15
- export { Slider } from './Slider';
16
- export { Switch } from './Switch';
1
+ export { Button } from './Button';
2
+ export { ButtonGroup } from './ButtonGroup';
3
+ export { Cascader } from './Cascader';
4
+ export { Chart } from './Chart';
5
+ export { DatePicker } from './DatePicker';
6
+ export { Form } from './Form';
7
+ export { Incomplete } from './Incomplete';
8
+ export { MultipleChoiceQuestion } from './MultipleChoiceQuestion';
9
+ export { NumberInput } from './NumberInput';
10
+ export { Quiz } from './Quiz';
11
+ export { RadioGroup } from './Radio';
12
+ export { Select } from './Select';
13
+ export { SelectMulti } from './SelectMulti';
14
+ export { TreeSelect } from './TreeSelect';
15
+ export { ShortAnswerQuestion } from './ShortAnswerQuestion';
16
+ export { Slider } from './Slider';
17
+ export { Switch } from './Switch';
17
18
  export { TextInput } from './TextInput';
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './lib';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
- export interface MarkdownUIProps {
3
- html: string;
4
- onWidgetEvent?: (event: CustomEvent<{
5
- id: string;
6
- value: unknown;
7
- }>) => void;
8
- }
9
- export declare const MarkdownUI: React.FC<MarkdownUIProps>;
10
- //# sourceMappingURL=MarkdownUI.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MarkdownUI.d.ts","sourceRoot":"","sources":["../../src/lib/MarkdownUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAIjD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,CAAC,KAAK,IAAI,CAAC;CAC5E;AAuCD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0BhD,CAAC"}
@@ -1,4 +0,0 @@
1
- export { MarkdownUI } from './MarkdownUI';
2
- export type { MarkdownUIProps } from './MarkdownUI';
3
- export * from '../widgets';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,cAAc,YAAY,CAAC"}
@@ -1,15 +0,0 @@
1
- import React from 'react';
2
- export interface ButtonProps {
3
- label?: string;
4
- /** 背景色(十六进制或 CSS 颜色名) */
5
- color?: string;
6
- /** 字体颜色(十六进制或 CSS 颜色名) */
7
- textColor?: string;
8
- /** 尺寸:small / medium / large,默认 medium */
9
- size?: 'small' | 'medium' | 'large';
10
- /** 是否禁用 */
11
- disabled?: boolean;
12
- onchange: (value: string) => void;
13
- }
14
- export declare const Button: React.FC<ButtonProps>;
15
- //# sourceMappingURL=Button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/widgets/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAuBxC,CAAC"}
@@ -1,11 +0,0 @@
1
- import React from 'react';
2
- export interface ButtonGroupProps {
3
- choices: string[];
4
- label?: string;
5
- default?: string;
6
- /** 是否禁用 */
7
- disabled?: boolean;
8
- onchange: (value: string) => void;
9
- }
10
- export declare const ButtonGroup: React.FC<ButtonGroupProps>;
11
- //# sourceMappingURL=ButtonGroup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ButtonGroup.d.ts","sourceRoot":"","sources":["../../src/widgets/ButtonGroup.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAkClD,CAAC"}
@@ -1,34 +0,0 @@
1
- import React from 'react';
2
- export interface CascaderProps {
3
- choices: string[];
4
- /** 嵌套对象树数据源(与扁平路径 choices 兼容共存,优先于 choices) */
5
- data?: CascadeNode[];
6
- /** 远端数据源 URL:设置后运行时 fetch 拉取嵌套树,data/choices 作为初始/后备树 */
7
- url?: string;
8
- /** 懒加载模式(url 存在时生效):首次只拉根级,点击父级后以 url?parent=<value> 逐级请求子级 */
9
- lazy?: boolean;
10
- label?: string;
11
- default?: string;
12
- placeholder?: string;
13
- hint?: string;
14
- required?: boolean;
15
- /** 校验失败提示文案 */
16
- message?: string;
17
- /** 外部(form 提交时)传入的错误信息 */
18
- error?: string;
19
- /** 是否禁用 */
20
- disabled?: boolean;
21
- onchange: (value: string) => void;
22
- }
23
- /** 级联数据节点(嵌套树形,对应 mdui-lang 的 CascadeNode)
24
- * 取值字段兼容 value/key(无 value 时用 key);展示字段 label 缺省回退 value/key */
25
- export interface CascadeNode {
26
- value?: string | number;
27
- /** value 的别名(key:label 风格数据源) */
28
- key?: string | number;
29
- label?: string | number;
30
- children?: CascadeNode[];
31
- [extra: string]: any;
32
- }
33
- export declare const Cascader: React.FC<CascaderProps>;
34
- //# sourceMappingURL=Cascader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Cascader.d.ts","sourceRoot":"","sources":["../../src/widgets/Cascader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;iEACiE;AACjE,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AA+FD,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA8Q5C,CAAC"}
@@ -1,20 +0,0 @@
1
- interface Dataset {
2
- label: string;
3
- data: number[];
4
- }
5
- interface ChartProps {
6
- type: "chart-line" | "chart-bar" | "chart-pie" | "chart-scatter";
7
- title?: string;
8
- height?: number;
9
- /** 远端数据源 URL:设置后运行时 fetch 拉取(CSV 文本或 JSON),本地 CSV 作为初始/后备数据 */
10
- url?: string;
11
- /** 是否展示图例:未设置(undefined)时自动判断(多数据集或饼图时展示) */
12
- legend?: boolean;
13
- labels: string[];
14
- datasets: Dataset[];
15
- options?: Record<string, any>;
16
- onchange: (data: any) => void;
17
- }
18
- export declare function Chart({ type, title, height, url, legend, labels, datasets, options, onchange }: ChartProps): import("react/jsx-runtime").JSX.Element;
19
- export {};
20
- //# sourceMappingURL=Chart.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/widgets/Chart.tsx"],"names":[],"mappings":"AAoCA,UAAU,OAAO;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,eAAe,CAAC;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/B;AAED,wBAAgB,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAY,EAAE,QAAQ,EAAE,EAAE,UAAU,2CAsLpH"}
@@ -1,28 +0,0 @@
1
- import React from 'react';
2
- export interface DatePickerProps {
3
- label?: string;
4
- /** 选择模式:date 仅日期(默认)/ datetime 日期+时间 */
5
- picker?: 'date' | 'datetime';
6
- /** 范围选择(antd RangePicker 效果:双月历面板) */
7
- range?: boolean;
8
- /** 默认值:时间戳(毫秒)或格式化时间字符串;range 模式为 [start, end] */
9
- default?: number | string | (number | string)[];
10
- /** 显示格式:默认按模式推导——date 为 YYYY-MM-DD,datetime 为 YYYY-MM-DD HH:mm:ss */
11
- format?: string;
12
- placeholder?: string;
13
- /** 禁用当前日期之前的日期 */
14
- disableBeforeNow?: boolean;
15
- /** 禁用当前日期之后的日期 */
16
- disableAfterNow?: boolean;
17
- hint?: string;
18
- required?: boolean;
19
- /** 校验失败提示文案 */
20
- message?: string;
21
- /** 外部(form 提交时)传入的错误信息 */
22
- error?: string;
23
- /** 是否禁用(整组件不可交互,区别于 disableBeforeNow/disableAfterNow 的部分日期禁用) */
24
- disabled?: boolean;
25
- onchange: (value: number | number[] | null) => void;
26
- }
27
- export declare const DatePicker: React.FC<DatePickerProps>;
28
- //# sourceMappingURL=DatePicker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../src/widgets/DatePicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,sCAAsC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAChD,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;CACrD;AAiCD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAsXhD,CAAC"}
@@ -1,47 +0,0 @@
1
- import React from 'react';
2
- export interface FieldWhen {
3
- /** 依赖的字段 id */
4
- field: string;
5
- /** 依赖字段命中这些值之一时才展示 */
6
- values: string[];
7
- }
8
- /** 条件组合:all 且组(全部命中)、any 或组(任一命中),两组同时存在取交集 */
9
- export interface FieldWhenGroup {
10
- all?: FieldWhen[];
11
- any?: FieldWhen[];
12
- }
13
- export interface Field {
14
- type: string;
15
- id: string;
16
- /** 在 row 内占据的栅格数(1-24,类似 antd Col 的 span) */
17
- span?: number;
18
- /** 条件显示:依赖字段的取值命中时才展示;
19
- * 多条件时为数组(AND 组合:全部命中才显示);
20
- * 分组形态 { all, any }:且组全部命中 且 或组任一命中 */
21
- when?: FieldWhen | FieldWhen[] | FieldWhenGroup;
22
- [key: string]: any;
23
- }
24
- export interface FormRow {
25
- /** 列间距(px),类似 antd Row 的 gutter */
26
- gutter?: number;
27
- fields: Field[];
28
- }
29
- export interface FormProps {
30
- fields: Field[];
31
- /** 行分组(对象形态 { gutter, fields };兼容旧数组形态 Field[][]) */
32
- rows?: (FormRow | Field[])[];
33
- inline?: boolean;
34
- columns?: number;
35
- submitLabel?: string;
36
- /** 取消按钮文案,未设置则不显示 */
37
- cancelLabel?: string;
38
- /** 清空/重置按钮文案,未设置则不显示 */
39
- resetLabel?: string;
40
- /** 按钮组对齐:left / center / right */
41
- buttonsAlign?: 'left' | 'center' | 'right';
42
- /** 是否禁用:级联禁用所有字段与按钮 */
43
- disabled?: boolean;
44
- onchange: (values: Record<string, unknown>) => void;
45
- }
46
- export declare const Form: React.FC<FormProps>;
47
- //# sourceMappingURL=Form.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../src/widgets/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAe5D,MAAM,WAAW,SAAS;IACxB,eAAe;IACf,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;4CAEwC;IACxC,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,GAAG,cAAc,CAAC;IAChD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,qDAAqD;IACrD,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,EAAE,CAAC,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CAmTpC,CAAC"}
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- export declare const Incomplete: React.FC;
3
- //# sourceMappingURL=Incomplete.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Incomplete.d.ts","sourceRoot":"","sources":["../../src/widgets/Incomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAQ9B,CAAC"}
@@ -1,15 +0,0 @@
1
- import React from 'react';
2
- export interface MultipleChoiceQuestionProps {
3
- question: string;
4
- choices: string[];
5
- correctAnswer?: string;
6
- showFeedback?: boolean;
7
- /** 是否禁用:禁用后选项不可点击 */
8
- disabled?: boolean;
9
- onchange: (value: {
10
- answer: string;
11
- isCorrect?: boolean;
12
- }) => void;
13
- }
14
- export declare const MultipleChoiceQuestion: React.FC<MultipleChoiceQuestionProps>;
15
- //# sourceMappingURL=MultipleChoiceQuestion.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MultipleChoiceQuestion.d.ts","sourceRoot":"","sources":["../../src/widgets/MultipleChoiceQuestion.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACpE;AAED,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAoExE,CAAC"}