cdui-js 1.0.16 → 1.0.17

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.
package/css/canlendar.css CHANGED
@@ -1,4 +1,5 @@
1
- .canlendar {
1
+ .canlendar,
2
+ .monthwidget {
2
3
  max-width: 380px;
3
4
  height: 320px;
4
5
  border-radius: 12px;
@@ -8,21 +9,25 @@
8
9
  }
9
10
 
10
11
  .canlendar-header,
11
- .canlendar-weeks {
12
+ .canlendar-weeks,
13
+ .monthwidget-header {
12
14
  display: flex;
13
15
  align-items: center;
14
16
  height: 36px;
15
17
  line-height: 36px;
16
18
  }
17
19
 
18
- .canlendar-month {
20
+ .canlendar-title,
21
+ .monthwidget-title {
19
22
  flex: auto;
20
23
  padding-left: 12px;
21
24
  font-weight: bold;
22
25
  font-size: 14px;
26
+ cursor: pointer;
23
27
  }
24
28
 
25
- .canlendar-header > .icon {
29
+ .canlendar-header > .icon,
30
+ .monthwidget-header > .icon {
26
31
  box-sizing: border-box;
27
32
  width: 40px;
28
33
  height: 100%;
@@ -40,7 +45,8 @@
40
45
  height: calc(100% - 72px);
41
46
  }
42
47
 
43
- .canlendar-date {
48
+ .canlendar-date,
49
+ .monthwidget-month {
44
50
  display: inline-flex;
45
51
  justify-content: center;
46
52
  align-items: center;
@@ -49,17 +55,22 @@
49
55
  cursor: pointer;
50
56
  }
51
57
 
52
- .canlendar-date.disabled {
58
+ .canlendar-date.disabled,
59
+ .monthwidget-month.disabled {
53
60
  cursor: not-allowed;
54
61
  }
55
62
 
56
63
  .canlendar-date.today,
57
- .canlendar-date.selected {
64
+ .canlendar-date.selected,
65
+ .monthwidget-month.today,
66
+ .monthwidget-month.selected {
58
67
  position: relative;
59
68
  }
60
69
 
61
70
  .canlendar-date.today::before,
62
- .canlendar-date.selected::before {
71
+ .canlendar-date.selected::before,
72
+ .monthwidget-month.today::before,
73
+ .monthwidget-month.selected::before {
63
74
  position: absolute;
64
75
  content: '';
65
76
  width: 40px;
package/demo/src/App.tsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import { batch, createEffect, omitProps, pickProps, reactive } from '../../src/reactive';
2
+ import { Icon } from '../../src/components/Icon';
2
3
  import { CanlendarPage } from './pages/Canlendar';
3
4
  import { ComboBoxPage } from './pages/ComboBox';
4
5
  import { DatePickerPage } from './pages/DatePicker';
@@ -8,8 +9,8 @@ import { MobileDatePickerPage } from './pages/MobileDatePicker';
8
9
  const Test = (props: { text1: string; text2: string }) => {
9
10
  return (
10
11
  <div>
11
- <div>{JSON.stringify({ ...pickProps(props, ['text1']) })}</div>
12
- <div>{JSON.stringify({ ...omitProps(props, ['text1']) })}</div>
12
+ <div>{pickProps(props, ['text1']).text1}</div>
13
+ <div>{omitProps(props, ['text1']).text2}</div>
13
14
  </div>
14
15
  );
15
16
  };
@@ -26,8 +27,9 @@ export const App = () => {
26
27
 
27
28
  return (
28
29
  <div style={{ 'min-height': '100%' }}>
30
+ <Icon name="dropdown" class="test"></Icon>
29
31
  <Test {...state}></Test>
30
- <button onclick={() => (state.text1 = state.text2 = '' + Math.random())}>click</button>
32
+ <button onclick={() => batch(() => (state.text1 = state.text2 = '' + Math.random()))}>click</button>
31
33
  <CanlendarPage></CanlendarPage>
32
34
  <DatePickerPage></DatePickerPage>
33
35
  <MobileDatePickerPage></MobileDatePickerPage>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdui-js",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "bin": {
@@ -12,14 +12,14 @@ const renderDates = (
12
12
  from: number,
13
13
  to: number,
14
14
  className: string,
15
- todayDate: Date,
16
- selectedDate?: Date,
15
+ todayValue: Date,
16
+ selectedValue?: Date,
17
17
  disableFn?: (year: number, month: number, date: number) => boolean,
18
18
  ) => {
19
- let today = todayDate.getFullYear() === year && todayDate.getMonth() === month ? todayDate.getDate() : -1;
19
+ let today = todayValue.getFullYear() === year && todayValue.getMonth() === month ? todayValue.getDate() : -1;
20
20
  let selected =
21
- selectedDate && selectedDate.getFullYear() === year && selectedDate.getMonth() === month
22
- ? selectedDate.getDate()
21
+ selectedValue && selectedValue.getFullYear() === year && selectedValue.getMonth() === month
22
+ ? selectedValue.getDate()
23
23
  : -1;
24
24
 
25
25
  for (let i = from; i <= to; i++) {
@@ -37,8 +37,8 @@ const renderPrevMonthItems = (
37
37
  year: number,
38
38
  month: number,
39
39
  index: number,
40
- todayDate: Date,
41
- selectedDate?: Date,
40
+ todayValue: Date,
41
+ selectedValue?: Date,
42
42
  disableFn?: (year: number, month: number, date: number) => boolean,
43
43
  ) => {
44
44
  // 获取上月天数
@@ -51,7 +51,7 @@ const renderPrevMonthItems = (
51
51
  month = 11;
52
52
  }
53
53
 
54
- renderDates(items, year, month, days - index + 1, days, ' prev-month', todayDate, selectedDate, disableFn);
54
+ renderDates(items, year, month, days - index + 1, days, ' prev-month', todayValue, selectedValue, disableFn);
55
55
  };
56
56
 
57
57
  const renderNextMonthItems = (
@@ -59,8 +59,8 @@ const renderNextMonthItems = (
59
59
  year: number,
60
60
  month: number,
61
61
  days: number,
62
- todayDate: Date,
63
- selectedDate?: Date,
62
+ todayValue: Date,
63
+ selectedValue?: Date,
64
64
  disableFn?: (year: number, month: number, date: number) => boolean,
65
65
  ) => {
66
66
  if (month < 11) {
@@ -70,17 +70,17 @@ const renderNextMonthItems = (
70
70
  month = 0;
71
71
  }
72
72
 
73
- renderDates(items, year, month, 1, days, ' next-month', todayDate, selectedDate, disableFn);
73
+ renderDates(items, year, month, 1, days, ' next-month', todayValue, selectedValue, disableFn);
74
74
  };
75
75
 
76
76
  const renderItems = (
77
- showDate: Date,
78
- selectedDate?: Date,
77
+ currentValue: Date,
78
+ selectedValue?: Date,
79
79
  disableFn?: (year: number, month: number, date: number) => boolean,
80
80
  ) => {
81
81
  let today = new Date();
82
- let year = showDate.getFullYear();
83
- let month = showDate.getMonth();
82
+ let year = currentValue.getFullYear();
83
+ let month = currentValue.getMonth();
84
84
  let firstDate = new Date(year, month, 1); // 获取当前月的第一天
85
85
 
86
86
  let firstWeek = firstDate.getDay();
@@ -91,17 +91,17 @@ const renderItems = (
91
91
  // 当前月第一天不是周一,渲染上月数据
92
92
  if (firstWeek !== 1) {
93
93
  index = firstWeek > 0 ? firstWeek - 1 : 6;
94
- renderPrevMonthItems(items, year, month, index, today, selectedDate, disableFn);
94
+ renderPrevMonthItems(items, year, month, index, today, selectedValue, disableFn);
95
95
  }
96
96
 
97
97
  // 获取当前月的天数
98
98
  days = new Date(year, month + 1, 0).getDate();
99
99
  // 渲染本月日期
100
- renderDates(items, year, month, 1, days, '', today, selectedDate, disableFn);
100
+ renderDates(items, year, month, 1, days, '', today, selectedValue, disableFn);
101
101
 
102
102
  // 当前月最后一天没有占满,渲染下月数据
103
103
  if ((index += days) < 42) {
104
- renderNextMonthItems(items, year, month, 42 - index, today, selectedDate, disableFn);
104
+ renderNextMonthItems(items, year, month, 42 - index, today, selectedValue, disableFn);
105
105
  }
106
106
 
107
107
  return items.join('');
@@ -155,22 +155,22 @@ export const Canlendar = (
155
155
  disableFn?: (year: number, month: number, date: number) => boolean;
156
156
  },
157
157
  ) => {
158
- let domMonth: HTMLElement;
158
+ let domTitle: HTMLElement;
159
159
  let domBody: HTMLElement;
160
160
 
161
- const [selectedDate, setSelectedDate] = createSignal(parseDate(props.value));
162
- const [showDate, setShowDate] = createSignal(selectedDate() || new Date());
161
+ const [selectedValue, setSelectedDate] = createSignal(parseDate(props.value));
162
+ const [currentValue, setCurrentValue] = createSignal(selectedValue() || new Date());
163
163
 
164
164
  return (
165
165
  <div class={combineClass('canlendar', props.class)} {...omitProps(props, OMIT_PROPS)}>
166
166
  <div class="canlendar-header">
167
- <div ref={domMonth as any} class="canlendar-month">
168
- {replaceTemplate(i18n.Month, showDate().getFullYear(), formatMonth(showDate()))}
167
+ <div ref={domTitle as any} class="canlendar-title">
168
+ {replaceTemplate(i18n.Month, currentValue().getFullYear(), formatMonth(currentValue()))}
169
169
  </div>
170
- <svg class="icon icon-s" aria-hidden={true} onclick={() => setShowDate(switchMonth(showDate(), -1))}>
170
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(switchMonth(currentValue(), -1))}>
171
171
  <use href="#icon-backward"></use>
172
172
  </svg>
173
- <svg class="icon icon-s" aria-hidden={true} onclick={() => setShowDate(switchMonth(showDate(), 1))}>
173
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(switchMonth(currentValue(), 1))}>
174
174
  <use href="#icon-forward"></use>
175
175
  </svg>
176
176
  </div>
@@ -196,7 +196,7 @@ export const Canlendar = (
196
196
  }
197
197
  }
198
198
  }}
199
- innerHTML={renderItems(showDate(), selectedDate(), props.disableFn)}
199
+ innerHTML={renderItems(currentValue(), selectedValue(), props.disableFn)}
200
200
  ></div>
201
201
  </div>
202
202
  );
@@ -5,12 +5,38 @@ import { Canleandar as i18n } from '../i18n';
5
5
  import { replaceTemplate } from '../template';
6
6
  import { For } from './For';
7
7
 
8
+ const formatMonth = (month: number) => {
9
+ return month > 9 ? month : '0' + month;
10
+ };
11
+
12
+ const getCurrentMonth = () => {
13
+ let date = new Date();
14
+ return [date.getFullYear(), date.getMonth() + 1];
15
+ };
16
+
17
+ const switchMonth = (value: [year: number, month: number], offset: 1 | -1) => {
18
+ let year = value[0];
19
+ let month = value[1] + offset;
20
+
21
+ if (month === 0) {
22
+ month = 12;
23
+ year--;
24
+ } else if (month > 12) {
25
+ month = 1;
26
+ year++;
27
+ }
28
+
29
+ return [year, month];
30
+ };
31
+
32
+ const MONTH_LIST = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
33
+
8
34
  export const MonthWidget = (
9
35
  props: Omit<JSX.HTMLAttributes<never>, 'children'> & {
10
36
  /**
11
- * 日期值
37
+ * 年月值
12
38
  */
13
- value?: Date | string | number;
39
+ value?: [year: number, month: number];
14
40
  /**
15
41
  * 值变更事件
16
42
  */
@@ -21,21 +47,46 @@ export const MonthWidget = (
21
47
  disableFn?: (year: number, month: number, date: number) => boolean;
22
48
  },
23
49
  ) => {
50
+ let domTitle: HTMLElement;
24
51
  let domBody: HTMLElement;
25
52
 
53
+ const [selectedValue, setSelectedDate] = createSignal(props.value);
54
+ const [currentValue, setCurrentValue] = createSignal(selectedValue() || getCurrentMonth());
55
+
26
56
  return (
27
57
  <div>
28
- {/* <div class="canlendar-header">
29
- <div ref={domBody as any} class="canlendar-month">
30
- {replaceTemplate(i18n.Month, showDate().getFullYear(), formatMonth(showDate()))}
58
+ <div class="monthwidget-header">
59
+ <div ref={domTitle as any} class="monthwidget-title">
60
+ {replaceTemplate(i18n.Month, currentValue()[0], formatMonth(currentValue()[1]))}
31
61
  </div>
32
- <svg class="icon icon-s" aria-hidden={true} onclick={() => setShowDate(switchMonth(showDate(), -1))}>
62
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(switchMonth(selectedValue(), -1))}>
33
63
  <use href="#icon-backward"></use>
34
64
  </svg>
35
- <svg class="icon icon-s" aria-hidden={true} onclick={() => setShowDate(switchMonth(showDate(), 1))}>
65
+ <svg class="icon icon-s" aria-hidden={true} onclick={() => setCurrentValue(switchMonth(selectedValue(), 1))}>
36
66
  <use href="#icon-forward"></use>
37
67
  </svg>
38
- </div> */}
68
+ </div>
69
+ <div
70
+ ref={domBody as any}
71
+ class="monthwidget-body"
72
+ onclick={(event) => {
73
+ let target = event.target as HTMLElement;
74
+ let value, onValueChange;
75
+
76
+ if (target && (onValueChange = props.onValueChange)) {
77
+ let dom = domBody.querySelector('.selected') as HTMLElement;
78
+
79
+ if (dom !== target) {
80
+ value = [currentValue()[0], +target.textContent];
81
+
82
+ setSelectedDate(value);
83
+ onValueChange(value);
84
+ }
85
+ }
86
+ }}
87
+ >
88
+ <For each={MONTH_LIST}>{(item) => <span>{item}</span>}</For>
89
+ </div>
39
90
  </div>
40
91
  );
41
92
  };
package/src/reactive.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Component, createEffect, createSignal, createUniqueId, lazy } from 'solid-js';
1
+ import { Component, createEffect, createSignal, createUniqueId, lazy, splitProps } from 'solid-js';
2
2
 
3
3
  const getOwnPropertyNames = Object.getOwnPropertyNames;
4
4
 
@@ -91,31 +91,58 @@ export interface SSRRenderPage {
91
91
  * @param pickPropertyNames 要选择的组件属性名集合
92
92
  */
93
93
  export const pickProps = <T extends Record<any, any>, K extends readonly (keyof T)[]>(
94
- properties: T,
94
+ props: T,
95
95
  pickPropertyNames: K,
96
96
  ): Pick<T, K[number]> => {
97
- return new Proxy(properties, {
98
- ownKeys(target) {
99
- return getOwnPropertyNames(target).filter((key) => pickPropertyNames.indexOf(key) >= 0);
100
- },
101
- });
97
+ let result = {};
98
+
99
+ for (let i = 0, l = pickPropertyNames.length; i < l; i++) {
100
+ let name = pickPropertyNames[i];
101
+
102
+ defineProperty(result, name, {
103
+ get: () => props[name],
104
+ });
105
+ }
106
+
107
+ return result as Pick<T, K[number]>;
108
+ // return new Proxy(props, {
109
+ // ownKeys(target) {
110
+ // return getOwnPropertyNames(target).filter((key) => pickPropertyNames.indexOf(key) >= 0);
111
+ // },
112
+ // });
102
113
  };
103
114
 
104
115
  /**
105
116
  * 排除部分组件属性
106
117
  *
107
- * @param properties 组件属性集合
118
+ * @param props 组件属性集合
108
119
  * @param omitPropertyNames 要排除的组件属性名集合
109
120
  */
110
121
  export const omitProps = <T extends Record<any, any>, K extends readonly (keyof T)[]>(
111
- properties: T,
122
+ props: T,
112
123
  omitPropertyNames: K,
113
124
  ): Omit<T, K[number]> => {
114
- return new Proxy(properties, {
115
- ownKeys(target) {
116
- return getOwnPropertyNames(target).filter((key) => omitPropertyNames.indexOf(key) < 0);
117
- },
118
- }) as unknown as Exclude<T, K[number]>;
125
+ let names = getOwnPropertyNames(props);
126
+ let result = {};
127
+
128
+ for (let i = 0, l = names.length; i < l; i++) {
129
+ let name = names[i];
130
+
131
+ if (omitPropertyNames.indexOf(name) < 0) {
132
+ defineProperty(result, name, {
133
+ get: () => props[name],
134
+ });
135
+ }
136
+ }
137
+
138
+ return result as Omit<T, K[number]>;
139
+
140
+ // return splitProps(props, omitPropertyNames)[1] as any;
141
+ // return new Proxy(props, {
142
+ // ownKeys(target) {
143
+ // return getOwnPropertyNames(target).filter((key) => omitPropertyNames.indexOf(key) < 0);
144
+ // },
145
+ // }) as unknown as Omit<T, K[number]>;
119
146
  };
120
147
 
121
148
  /**