cdui-js 1.0.22 → 1.0.24

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.
@@ -1,20 +1,16 @@
1
1
  import { JSX } from '../jsx';
2
2
  import { MonthWidget as i18n } from '../i18n';
3
3
  import { replaceTemplate } from '../template';
4
- import { createSignal, combineClass } from '../reactive';
4
+ import { createSignal, combineClass, omitProps, render } from '../reactive';
5
5
  import { For } from './For';
6
-
7
- const getCurrentMonth = () => {
8
- let date = new Date();
9
- return [date.getFullYear(), date.getMonth() + 1] as [year: number, month: number];
10
- };
6
+ import { YearWidget } from './YearWidget';
11
7
 
12
8
  const MONTH_LIST = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
13
9
 
14
10
  const MonthItem = (props: {
15
11
  value: number;
16
12
  selectedValue: [year: number, month: number];
17
- currentValue: [year: number, month: number];
13
+ currentValue: number;
18
14
  onclick: (event: Event) => void;
19
15
  disableFn?: (year: number, month: number) => boolean;
20
16
  }) => {
@@ -28,23 +24,21 @@ const MonthItem = (props: {
28
24
 
29
25
  const checkCurrent = () => {
30
26
  const today = new Date();
31
- const currentValue = props.currentValue;
32
27
 
33
- return today.getFullYear() === currentValue[0] + year && today.getMonth() + 1 === month;
28
+ return today.getFullYear() === props.currentValue + year && today.getMonth() + 1 === month;
34
29
  };
35
30
 
36
31
  const checkSelected = () => {
37
32
  let selectedValue = props.selectedValue;
38
- const currentValue = props.currentValue;
39
33
 
40
- return selectedValue && selectedValue[0] === currentValue[0] + year && selectedValue[1] === month;
34
+ return selectedValue && selectedValue[0] === props.currentValue + year && selectedValue[1] === month;
41
35
  };
42
36
 
43
37
  return (
44
38
  <span
45
39
  class={`datewidget-item${year ? ' next-block' : ''}${checkCurrent() ? ' today' : ''}${
46
40
  checkSelected() ? ' selected' : ''
47
- }${props.disableFn && props.disableFn(props.currentValue[0] + year, month) ? ' disabled' : ''}`}
41
+ }${props.disableFn && props.disableFn(props.currentValue + year, month) ? ' disabled' : ''}`}
48
42
  data-month={`${year}|${month}`}
49
43
  onclick={props.onclick}
50
44
  >
@@ -53,11 +47,38 @@ const MonthItem = (props: {
53
47
  );
54
48
  };
55
49
 
50
+ const showYearWidget = (
51
+ dom: HTMLElement,
52
+ setCurrentValue: (value) => void,
53
+ selectedValue?: [year: number, month: number],
54
+ ) => {
55
+ render(
56
+ () => (
57
+ <YearWidget
58
+ value={selectedValue && selectedValue[0]}
59
+ style={{ position: 'absolute', top: '0', left: '0', width: '100%', border: 'none' }}
60
+ onchange={(event) => {
61
+ let result = event.detail;
62
+
63
+ dom.removeChild(event.target as HTMLElement);
64
+
65
+ if (!selectedValue || result !== selectedValue[0]) {
66
+ setCurrentValue(result);
67
+ }
68
+ }}
69
+ ></YearWidget>
70
+ ),
71
+ dom,
72
+ );
73
+ };
74
+
75
+ const OMIT_PROPS = ['class', 'value', 'disableFn'] as const;
76
+
56
77
  /**
57
78
  * 月份组件
58
79
  */
59
80
  export const MonthWidget = (
60
- props: Omit<JSX.HTMLAttributes<never>, 'children'> & {
81
+ props: Omit<JSX.HTMLAttributes<never>, 'children' | 'onchange'> & {
61
82
  /**
62
83
  * 年月值
63
84
  */
@@ -65,55 +86,63 @@ export const MonthWidget = (
65
86
  /**
66
87
  * 值变更事件
67
88
  */
68
- onValueChange?: (value: Date) => void;
89
+ onchange?: (value: CustomEvent<[year: number, month: number]>) => void;
69
90
  /**
70
91
  * 禁用函数
71
92
  */
72
93
  disableFn?: (year: number, month: number) => boolean;
73
94
  },
74
95
  ) => {
75
- let domTitle: HTMLElement;
76
- let domBody: HTMLElement;
96
+ let dom: HTMLElement;
77
97
 
78
98
  const [selectedValue, setSelectedValue] = createSignal(props.value);
79
- const [currentValue, setCurrentValue] = createSignal(selectedValue() || getCurrentMonth());
99
+ const [currentValue, setCurrentValue] = createSignal(selectedValue() ? selectedValue()[0] : new Date().getFullYear());
80
100
 
81
101
  const onclick = (event: Event) => {
82
102
  let target = event.currentTarget as HTMLElement;
83
103
  let month = target.dataset.month as any;
84
104
 
85
105
  // 没有选中
86
- if (month && !target.classList.contains('selected')) {
87
- month = month.split('|');
88
- month = [currentValue()[0] + (month[0] | 0), month[1] | 0];
106
+ if (month) {
107
+ // 父节点
108
+ let parent = dom.parentNode as HTMLElement;
109
+ // 是否嵌入到日历组件中
110
+ let inline = parent.classList.contains('datewidget');
89
111
 
90
- setSelectedValue(month);
91
- props.onValueChange && props.onValueChange(month);
112
+ if (inline || !target.classList.contains('selected')) {
113
+ month = month.split('|');
114
+ month = [currentValue() + (month[0] | 0), month[1] | 0];
115
+
116
+ setSelectedValue(month);
117
+
118
+ dom.dispatchEvent(
119
+ new CustomEvent('change', {
120
+ detail: month,
121
+ bubbles: !inline, // 允许事件冒泡
122
+ }),
123
+ );
124
+ }
92
125
  }
93
126
  };
94
127
 
95
128
  return (
96
- <div class={combineClass('monthwidget datewidget', props.class)}>
129
+ <div
130
+ ref={dom as any}
131
+ class={combineClass('monthwidget datewidget', props.class)}
132
+ {...(omitProps(props, OMIT_PROPS) as any)}
133
+ >
97
134
  <div class="datewidget-header">
98
- <div ref={domTitle as any} class="datewidget-title">
99
- {replaceTemplate(i18n.Title, currentValue()[0])}
135
+ <div class="datewidget-title" onclick={() => showYearWidget(dom, setCurrentValue, selectedValue())}>
136
+ {replaceTemplate(i18n.Title, currentValue())}
100
137
  </div>
101
- <svg
102
- class="icon icon-s"
103
- aria-hidden={true}
104
- onclick={() => setCurrentValue([currentValue()[0] - 1, currentValue()[1]])}
105
- >
138
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(currentValue() - 1)}>
106
139
  <use href="#icon-backward"></use>
107
140
  </svg>
108
- <svg
109
- class="icon icon-s"
110
- aria-hidden={true}
111
- onclick={() => setCurrentValue([currentValue()[0] + 1, currentValue()[1]])}
112
- >
141
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(currentValue() + 1)}>
113
142
  <use href="#icon-forward"></use>
114
143
  </svg>
115
144
  </div>
116
- <div ref={domBody as any} class="datewidget-body">
145
+ <div class="datewidget-body">
117
146
  <For each={MONTH_LIST}>
118
147
  {(item) => (
119
148
  <MonthItem
@@ -11,7 +11,7 @@ export const YearPicker = (
11
11
  /**
12
12
  * 值变更事件
13
13
  */
14
- onValueChange?: (value: Date) => void;
14
+ onchange?: (event: CustomEvent<number>) => void;
15
15
  /**
16
16
  * 禁用函数
17
17
  */
@@ -1,188 +1,112 @@
1
1
  import { JSX } from '../jsx';
2
2
  import { YearWidget as i18n } from '../i18n';
3
3
  import { replaceTemplate } from '../template';
4
- import { createSignal, combineClass } from '../reactive';
5
- import { For } from './For';
4
+ import { createSignal, combineClass, omitProps } from '../reactive';
6
5
 
7
- // 渲染日期项
8
- const renderDates = (
6
+ // 渲染年项
7
+ const renderYears = (
9
8
  items: string[],
10
- year: number,
11
- month: number,
12
9
  from: number,
13
10
  to: number,
14
11
  className: string,
15
- todayValue: Date,
16
- selectedValue?: Date,
17
- disableFn?: (year: number, month: number, date: number) => boolean,
12
+ todayValue: number,
13
+ selectedValue?: number,
14
+ disableFn?: (year: number) => boolean,
18
15
  ) => {
19
- let today = todayValue.getFullYear() === year && todayValue.getMonth() === month ? todayValue.getDate() : -1;
20
- let selected =
21
- selectedValue && selectedValue.getFullYear() === year && selectedValue.getMonth() === month
22
- ? selectedValue.getDate()
23
- : -1;
24
-
25
- for (let i = from; i <= to; i++) {
16
+ for (let i = from; i < to; i++) {
26
17
  items.push(
27
- `<span class="datewidget-item${className}${today === i ? ' today' : ''}${selected === i ? ' selected' : ''}${
28
- disableFn && disableFn(year, month, i) ? ' disabled' : ''
29
- }" data-date="${year + '|' + month + '|' + i}">${i}</span>`,
18
+ `<span class="datewidget-item${className}${todayValue === i ? ' today' : ''}${selectedValue === i ? ' selected' : ''}${
19
+ disableFn && disableFn(i) ? ' disabled' : ''
20
+ }" data-year="${i}">${i}</span>`,
30
21
  );
31
22
  }
32
23
  };
33
24
 
34
- // 渲染上月日期项
35
- const renderPrevMonthItems = (
36
- items: string[],
37
- year: number,
38
- month: number,
39
- index: number,
40
- todayValue: Date,
41
- selectedValue?: Date,
42
- disableFn?: (year: number, month: number, date: number) => boolean,
43
- ) => {
44
- // 获取上月天数
45
- let days = new Date(year, month, 0).getDate();
46
-
47
- if (month > 0) {
48
- month--;
49
- } else {
50
- year--;
51
- month = 11;
52
- }
53
-
54
- renderDates(items, year, month, days - index + 1, days, ' prev-block', todayValue, selectedValue, disableFn);
55
- };
56
-
57
- const renderNextMonthItems = (
58
- items: string[],
59
- year: number,
60
- month: number,
61
- days: number,
62
- todayValue: Date,
63
- selectedValue?: Date,
64
- disableFn?: (year: number, month: number, date: number) => boolean,
65
- ) => {
66
- if (month < 11) {
67
- month++;
68
- } else {
69
- year++;
70
- month = 0;
71
- }
72
-
73
- renderDates(items, year, month, 1, days, ' next-block', todayValue, selectedValue, disableFn);
74
- };
75
-
76
- const renderItems = (
77
- currentValue: Date,
78
- selectedValue?: Date,
79
- disableFn?: (year: number, month: number, date: number) => boolean,
80
- ) => {
25
+ const renderItems = (currentValue: number, selectedValue?: number, disableFn?: (year: number) => boolean) => {
81
26
  let today = new Date();
82
- let year = currentValue.getFullYear();
83
- let month = currentValue.getMonth();
84
- let firstDate = new Date(year, month, 1); // 获取当前月的第一天
85
-
86
- let firstWeek = firstDate.getDay();
87
27
  let items = [];
88
- let index = 0;
89
- let days;
90
-
91
- // 当前月第一天不是周一,渲染上月数据
92
- if (firstWeek !== 1) {
93
- index = firstWeek > 0 ? firstWeek - 1 : 6;
94
- renderPrevMonthItems(items, year, month, index, today, selectedValue, disableFn);
95
- }
96
28
 
97
- // 获取当前月的天数
98
- days = new Date(year, month + 1, 0).getDate();
99
- // 渲染本月日期
100
- renderDates(items, year, month, 1, days, '', today, selectedValue, disableFn);
101
-
102
- // 当前月最后一天没有占满,渲染下月数据
103
- if ((index += days) < 42) {
104
- renderNextMonthItems(items, year, month, 42 - index, today, selectedValue, disableFn);
105
- }
29
+ // 渲染前面 10 年
30
+ renderYears(items, currentValue, currentValue + 10, '', today.getFullYear(), selectedValue, disableFn);
31
+
32
+ // 渲染后面 6
33
+ renderYears(
34
+ items,
35
+ currentValue + 10,
36
+ currentValue + 16,
37
+ ' next-block',
38
+ today.getFullYear(),
39
+ selectedValue,
40
+ disableFn,
41
+ );
106
42
 
107
43
  return items.join('');
108
44
  };
109
45
 
46
+ const OMIT_PROPS = ['class', 'value', 'disableFn'] as const;
47
+
110
48
  /**
111
49
  * 年份组件
112
50
  */
113
51
  export const YearWidget = (
114
- props: Omit<JSX.HTMLAttributes<never>, 'children'> & {
52
+ props: Omit<JSX.HTMLAttributes<never>, 'children' | 'onchange'> & {
115
53
  /**
116
- * 年月值
54
+ * 年值
117
55
  */
118
- value?: [year: number, month: number];
56
+ value?: number;
119
57
  /**
120
58
  * 值变更事件
121
59
  */
122
- onValueChange?: (value: Date) => void;
60
+ onchange?: (event: CustomEvent<number>) => void;
123
61
  /**
124
62
  * 禁用函数
125
63
  */
126
- disableFn?: (year: number, month: number) => boolean;
64
+ disableFn?: (year: number) => boolean;
127
65
  },
128
66
  ) => {
129
- let domTitle: HTMLElement;
130
- let domBody: HTMLElement;
131
-
132
- // const [selectedValue, setSelectedValue] = createSignal(props.value);
133
- // const [currentValue, setCurrentValue] = createSignal(selectedValue() || getCurrentMonth());
134
-
135
- // const onclick = (event: Event) => {
136
- // let target = event.currentTarget as HTMLElement;
137
- // let month = target.dataset.month as any;
67
+ let dom: HTMLElement;
138
68
 
139
- // // 没有选中
140
- // if (month && !target.classList.contains('selected')) {
141
- // month = month.split('|');
142
- // month = [currentValue()[0] + (month[0] | 0), month[1] | 0];
143
-
144
- // setSelectedValue(month);
145
- // props.onValueChange && props.onValueChange(month);
146
- // }
147
- // };
69
+ const [selectedValue, setSelectedValue] = createSignal(props.value);
70
+ const [currentValue, setCurrentValue] = createSignal((((selectedValue() || new Date().getFullYear()) / 10) | 0) * 10);
148
71
 
149
72
  return (
150
- <div class={combineClass('monthwidget datewidget', props.class)}>
151
- {/* <div class="datewidget-header">
152
- <div ref={domTitle as any} class="datewidget-title">
153
- {replaceTemplate(i18n.Title, currentValue()[0], formatMonth(currentValue()[1]))}
154
- </div>
155
- <svg
156
- class="icon icon-s"
157
- aria-hidden={true}
158
- onclick={() => setCurrentValue([currentValue()[0] - 1, currentValue()[1]])}
159
- >
73
+ <div
74
+ ref={dom as any}
75
+ class={combineClass('yearwidget datewidget', props.class)}
76
+ {...(omitProps(props, OMIT_PROPS) as any)}
77
+ >
78
+ <div class="datewidget-header">
79
+ <div class="datewidget-title">{replaceTemplate(i18n.Title, currentValue(), currentValue() + 9)}</div>
80
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(currentValue() - 10)}>
160
81
  <use href="#icon-backward"></use>
161
82
  </svg>
162
- <svg
163
- class="icon icon-s"
164
- aria-hidden={true}
165
- onclick={() => setCurrentValue([currentValue()[0] + 1, currentValue()[1]])}
166
- >
83
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(currentValue() + 10)}>
167
84
  <use href="#icon-forward"></use>
168
85
  </svg>
169
86
  </div>
170
87
  <div
171
- ref={domBody as any}
172
- class="datewidget-body canlendar-body"
88
+ class="datewidget-body yearwidget-body"
173
89
  onclick={(event) => {
174
90
  let target = event.target as HTMLElement;
175
- let date;
91
+ let year;
176
92
 
177
- while (target && target !== domBody) {
178
- if ((date = target.dataset.date)) {
179
- // 没有选中
180
- if (!target.classList.contains('selected')) {
181
- date = date.split('|');
182
- date = new Date(date[0] | 0, date[1] | 0, date[2] | 0);
93
+ while (target && target !== dom) {
94
+ if ((year = +target.dataset.year)) {
95
+ // 父节点
96
+ let parent = dom.parentNode as HTMLElement;
97
+ // 是否嵌入到年月组件中
98
+ let inline = parent.classList.contains('datewidget');
183
99
 
184
- setSelectedValue(date);
185
- props.onValueChange && props.onValueChange(date);
100
+ // 没有选中
101
+ if (inline || !target.classList.contains('selected')) {
102
+ setSelectedValue(year);
103
+
104
+ dom.dispatchEvent(
105
+ new CustomEvent('change', {
106
+ detail: year,
107
+ bubbles: !inline, // 允许事件冒泡
108
+ }),
109
+ );
186
110
  }
187
111
 
188
112
  break;
@@ -192,7 +116,7 @@ export const YearWidget = (
192
116
  }
193
117
  }}
194
118
  innerHTML={renderItems(currentValue(), selectedValue(), props.disableFn)}
195
- ></div> */}
119
+ ></div>
196
120
  </div>
197
121
  );
198
122
  };
@@ -1,15 +1,16 @@
1
1
  import { createRoot } from 'solid-js';
2
2
 
3
- import { JSX } from '../jsx';
3
+ import { JSX } from './jsx';
4
+ import { hideMaskLayer, showMaskLayer } from './dom';
4
5
 
5
6
  /**
6
7
  * 对话框
7
8
  */
8
9
  export type Dialog = HTMLElement & {
9
10
  /**
10
- * 关闭对话框方法
11
+ * 关闭对话框
11
12
  */
12
- close(): void;
13
+ close(destroy?: boolean): void;
13
14
  };
14
15
 
15
16
  /**
@@ -22,13 +23,19 @@ export const showDialog = (component: () => JSX.Element): Dialog => {
22
23
  return createRoot((dispose) => {
23
24
  let body = document.body;
24
25
  let dialog = component() as Dialog;
26
+ let style = dialog.style;
27
+
28
+ style.position = 'fixed';
29
+ style.zIndex = '9';
30
+
31
+ showMaskLayer();
25
32
 
26
- dialog.style.cssText = 'position:fixed;z-index:9';
27
33
  body.appendChild(dialog);
28
34
 
29
- dialog.close = () => {
35
+ dialog.close = (destroy?: boolean) => {
36
+ hideMaskLayer();
30
37
  body.removeChild(dialog);
31
- dispose();
38
+ destroy !== false && dispose();
32
39
  };
33
40
 
34
41
  return dialog;
package/src/i18n/index.ts CHANGED
@@ -13,7 +13,7 @@ export let MonthWidget = i18n.MonthWidget;
13
13
  /**
14
14
  * 日历
15
15
  */
16
- export let Canleandar = i18n.Canlendar;
16
+ export let Canlendar = i18n.Canlendar;
17
17
 
18
18
  /**
19
19
  * 表单
@@ -28,6 +28,6 @@ export let Form = i18n.Form;
28
28
  export const switchLanguage = (data: typeof i18n) => {
29
29
  YearWidget = i18n.YearWidget;
30
30
  MonthWidget = i18n.MonthWidget;
31
- Canleandar = i18n.Canlendar;
31
+ Canlendar = i18n.Canlendar;
32
32
  Form = i18n.Form;
33
33
  };
package/src/index.ts CHANGED
@@ -26,7 +26,9 @@ export * from './components/Form';
26
26
  export * from './components/CollapsiblePanel';
27
27
  export * from './components/Carousel';
28
28
  export * from './components/KeepAlive';
29
- export * from './components/Popup';
30
- export * from './components/Dialog';
29
+ // export * from './components/Popup';
30
+
31
+ export * from './popup';
32
+ export * from './dialog';
31
33
 
32
34
  export * from './ssr/render';