wx-svelte-core 1.3.0
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/license.txt +21 -0
- package/package.json +35 -0
- package/src/Locale.svelte +17 -0
- package/src/components/Area.svelte +70 -0
- package/src/components/Button.svelte +187 -0
- package/src/components/Calendar.svelte +42 -0
- package/src/components/Checkbox.svelte +132 -0
- package/src/components/CheckboxGroup.svelte +52 -0
- package/src/components/ColorBoard.svelte +311 -0
- package/src/components/ColorPicker.svelte +110 -0
- package/src/components/ColorSelect.svelte +204 -0
- package/src/components/Combo.svelte +228 -0
- package/src/components/Counter.svelte +178 -0
- package/src/components/DatePicker.svelte +115 -0
- package/src/components/DateRangePicker.svelte +138 -0
- package/src/components/Dropdown.svelte +125 -0
- package/src/components/Field.svelte +91 -0
- package/src/components/Globals.svelte +53 -0
- package/src/components/Icon.svelte +31 -0
- package/src/components/Modal.svelte +115 -0
- package/src/components/ModalArea.svelte +32 -0
- package/src/components/MultiCombo.svelte +279 -0
- package/src/components/Notice.svelte +145 -0
- package/src/components/Notices.svelte +20 -0
- package/src/components/Pager.svelte +131 -0
- package/src/components/Popup.svelte +53 -0
- package/src/components/Portal.svelte +42 -0
- package/src/components/RadioButton.svelte +129 -0
- package/src/components/RadioButtonGroup.svelte +50 -0
- package/src/components/RangeCalendar.svelte +134 -0
- package/src/components/RichSelect.svelte +149 -0
- package/src/components/Segmented.svelte +115 -0
- package/src/components/Select.svelte +124 -0
- package/src/components/SideArea.svelte +33 -0
- package/src/components/Slider.svelte +242 -0
- package/src/components/Switch.svelte +88 -0
- package/src/components/Tabs.svelte +163 -0
- package/src/components/Text.svelte +185 -0
- package/src/components/Timepicker.svelte +217 -0
- package/src/components/TwoState.svelte +60 -0
- package/src/components/calendar/Button.svelte +40 -0
- package/src/components/calendar/Duodecade.svelte +97 -0
- package/src/components/calendar/Header.svelte +105 -0
- package/src/components/calendar/Month.svelte +189 -0
- package/src/components/calendar/Panel.svelte +119 -0
- package/src/components/calendar/Year.svelte +89 -0
- package/src/components/calendar/helpers.js +56 -0
- package/src/components/helpers/SuggestDropdown.svelte +79 -0
- package/src/components/helpers/colorTransformator.js +146 -0
- package/src/components/helpers/colorValidation.js +21 -0
- package/src/components/helpers/listnav.js +85 -0
- package/src/components/helpers/sliderMove.js +42 -0
- package/src/components/helpers.js +6 -0
- package/src/index.js +50 -0
- package/src/themes/FontOpenSans.svelte +36 -0
- package/src/themes/FonttRoboto.svelte +19 -0
- package/src/themes/Material.svelte +321 -0
- package/src/themes/Willow.svelte +323 -0
- package/src/themes/WillowDark.svelte +320 -0
- package/whatsnew.md +97 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher } from "svelte";
|
|
3
|
+
import List from "./helpers/SuggestDropdown.svelte";
|
|
4
|
+
import { uid } from "wx-lib-dom";
|
|
5
|
+
|
|
6
|
+
export let value = "";
|
|
7
|
+
export let id = uid();
|
|
8
|
+
export let options = [];
|
|
9
|
+
export let textField = "label";
|
|
10
|
+
export let placeholder = "";
|
|
11
|
+
export let title = "";
|
|
12
|
+
export let disabled = false;
|
|
13
|
+
export let error = false;
|
|
14
|
+
export let clearButton = false;
|
|
15
|
+
|
|
16
|
+
const dispatch = createEventDispatcher();
|
|
17
|
+
|
|
18
|
+
let text = "";
|
|
19
|
+
let filterOptions = [];
|
|
20
|
+
|
|
21
|
+
let navigate;
|
|
22
|
+
let keydown;
|
|
23
|
+
function ready(ev) {
|
|
24
|
+
navigate = ev.detail.navigate;
|
|
25
|
+
keydown = ev.detail.keydown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let prevValue;
|
|
29
|
+
$: {
|
|
30
|
+
if (prevValue != value) {
|
|
31
|
+
text =
|
|
32
|
+
value || value === 0
|
|
33
|
+
? options.find(a => a.id === value)[textField]
|
|
34
|
+
: "";
|
|
35
|
+
prevValue = value;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
$: filterOptions = options;
|
|
39
|
+
|
|
40
|
+
function selectByEvent(ev) {
|
|
41
|
+
const id = ev.detail.id;
|
|
42
|
+
doSelect(id, true);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function selectByText(text) {
|
|
46
|
+
if (!options.length) return;
|
|
47
|
+
if (text === "" && clearButton) {
|
|
48
|
+
doUnselect();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let res = options.find(i => i[textField] === text);
|
|
53
|
+
if (!res) {
|
|
54
|
+
res = options.find(i =>
|
|
55
|
+
i[textField].toLowerCase().includes(text.toLowerCase())
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const id = res ? res.id : prevValue || options[0].id;
|
|
60
|
+
doSelect(id, false);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function doSelect(id, effects) {
|
|
64
|
+
if (id || id === 0) {
|
|
65
|
+
let selected = options.find(a => a.id === id);
|
|
66
|
+
text = selected[textField];
|
|
67
|
+
filterOptions = options;
|
|
68
|
+
|
|
69
|
+
if (effects) navigate(null);
|
|
70
|
+
|
|
71
|
+
if (value !== selected.id) {
|
|
72
|
+
value = selected.id;
|
|
73
|
+
dispatch("select", { selected });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!hasFocus && effects) inputElement.focus();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function doUnselect() {
|
|
81
|
+
text = value = "";
|
|
82
|
+
filterOptions = options;
|
|
83
|
+
dispatch("select", { selected: null });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function input() {
|
|
87
|
+
filterOptions = text
|
|
88
|
+
? options.filter(i =>
|
|
89
|
+
i[textField].toLowerCase().includes(text.toLowerCase())
|
|
90
|
+
)
|
|
91
|
+
: options;
|
|
92
|
+
if (filterOptions.length) navigate(0);
|
|
93
|
+
else navigate(null);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let inputElement,
|
|
97
|
+
hasFocus,
|
|
98
|
+
blurTimer = null;
|
|
99
|
+
function onFocus() {
|
|
100
|
+
hasFocus = true;
|
|
101
|
+
}
|
|
102
|
+
function onBlur() {
|
|
103
|
+
hasFocus = false;
|
|
104
|
+
blurTimer = setTimeout(() => {
|
|
105
|
+
if (!hasFocus) selectByText(text);
|
|
106
|
+
}, 200);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const index = () => filterOptions.findIndex(a => a.id === value);
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<div
|
|
113
|
+
class="wx-combo"
|
|
114
|
+
on:click={() => navigate(index())}
|
|
115
|
+
on:keydown={e => keydown(e, index())}
|
|
116
|
+
{title}
|
|
117
|
+
>
|
|
118
|
+
<input
|
|
119
|
+
{id}
|
|
120
|
+
bind:this={inputElement}
|
|
121
|
+
bind:value={text}
|
|
122
|
+
class:wx-error={error}
|
|
123
|
+
{disabled}
|
|
124
|
+
{placeholder}
|
|
125
|
+
on:focus={onFocus}
|
|
126
|
+
on:blur={onBlur}
|
|
127
|
+
on:input={input}
|
|
128
|
+
/>
|
|
129
|
+
|
|
130
|
+
{#if clearButton && !disabled && value}
|
|
131
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
132
|
+
<i class="wx-icon wxi-close" on:click|stopPropagation={doUnselect} />
|
|
133
|
+
{:else}<i class="wx-icon wxi-angle-down" />{/if}
|
|
134
|
+
|
|
135
|
+
{#if !disabled}
|
|
136
|
+
<List
|
|
137
|
+
let:option
|
|
138
|
+
items={filterOptions}
|
|
139
|
+
on:ready={ready}
|
|
140
|
+
on:select={selectByEvent}
|
|
141
|
+
>
|
|
142
|
+
<slot {option}>{option.name}</slot>
|
|
143
|
+
</List>
|
|
144
|
+
{/if}
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<style>
|
|
148
|
+
.wx-combo {
|
|
149
|
+
position: relative;
|
|
150
|
+
width: var(--wx-input-width);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
input {
|
|
154
|
+
display: block;
|
|
155
|
+
width: 100%;
|
|
156
|
+
height: var(--wx-input-height);
|
|
157
|
+
outline: none;
|
|
158
|
+
background: var(--wx-input-background);
|
|
159
|
+
border: var(--wx-input-border);
|
|
160
|
+
border-radius: var(--wx-input-border-radius);
|
|
161
|
+
font-family: var(--wx-input-font-family);
|
|
162
|
+
font-size: var(--wx-input-font-size);
|
|
163
|
+
line-height: var(--wx-input-line-height);
|
|
164
|
+
font-weight: var(--wx-input-font-weight);
|
|
165
|
+
text-align: var(--wx-input-text-align);
|
|
166
|
+
color: var(--wx-input-font-color);
|
|
167
|
+
padding: var(--wx-input-padding);
|
|
168
|
+
padding-right: calc(
|
|
169
|
+
var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2
|
|
170
|
+
);
|
|
171
|
+
overflow: hidden;
|
|
172
|
+
text-overflow: ellipsis;
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
}
|
|
175
|
+
input:focus {
|
|
176
|
+
border: var(--wx-input-border-focus);
|
|
177
|
+
}
|
|
178
|
+
input::placeholder {
|
|
179
|
+
color: var(--wx-input-placeholder-color);
|
|
180
|
+
}
|
|
181
|
+
input[disabled] {
|
|
182
|
+
cursor: not-allowed;
|
|
183
|
+
border: var(--wx-input-border-disabled);
|
|
184
|
+
color: var(--wx-color-font-disabled);
|
|
185
|
+
background: var(--wx-input-background-disabled);
|
|
186
|
+
}
|
|
187
|
+
input[disabled]::placeholder {
|
|
188
|
+
color: var(--wx-color-font-disabled);
|
|
189
|
+
}
|
|
190
|
+
input[disabled] ~ .wx-icon {
|
|
191
|
+
color: var(--wx-color-font-disabled);
|
|
192
|
+
}
|
|
193
|
+
input.wx-error {
|
|
194
|
+
border-color: var(--wx-color-danger);
|
|
195
|
+
color: var(--wx-color-danger);
|
|
196
|
+
}
|
|
197
|
+
input.wx-error ~ .wx-icon {
|
|
198
|
+
color: var(--wx-color-danger);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.wx-icon {
|
|
202
|
+
position: absolute;
|
|
203
|
+
right: var(--wx-input-icon-indent);
|
|
204
|
+
top: 50%;
|
|
205
|
+
transform: translateY(-50%);
|
|
206
|
+
font-size: var(--wx-input-icon-size);
|
|
207
|
+
line-height: 1;
|
|
208
|
+
width: var(--wx-input-icon-size);
|
|
209
|
+
height: var(--wx-input-icon-size);
|
|
210
|
+
display: flex;
|
|
211
|
+
justify-content: center;
|
|
212
|
+
align-items: center;
|
|
213
|
+
pointer-events: none;
|
|
214
|
+
user-select: none;
|
|
215
|
+
color: var(--wx-input-icon-color);
|
|
216
|
+
}
|
|
217
|
+
.wx-icon:before {
|
|
218
|
+
display: block;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.wx-icon.wxi-close {
|
|
222
|
+
pointer-events: all;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.wx-icon.wxi-close:hover {
|
|
226
|
+
color: var(--wx-color-danger);
|
|
227
|
+
}
|
|
228
|
+
</style>
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher } from "svelte";
|
|
3
|
+
import { uid } from "wx-lib-dom";
|
|
4
|
+
|
|
5
|
+
export let value = 0;
|
|
6
|
+
export let step = 1;
|
|
7
|
+
export let min = 0;
|
|
8
|
+
export let max = Infinity;
|
|
9
|
+
export let error = false;
|
|
10
|
+
export let disabled = false;
|
|
11
|
+
export let readonly = false;
|
|
12
|
+
|
|
13
|
+
const dispatch = createEventDispatcher();
|
|
14
|
+
|
|
15
|
+
function dec() {
|
|
16
|
+
if (readonly || value <= min) return;
|
|
17
|
+
value -= step;
|
|
18
|
+
dispatch("change", { value });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function inc() {
|
|
22
|
+
if (readonly || value >= max) return;
|
|
23
|
+
value += step;
|
|
24
|
+
dispatch("change", { value });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function blur() {
|
|
28
|
+
if (!readonly) {
|
|
29
|
+
const tValue =
|
|
30
|
+
Math.round(Math.min(max, Math.max(value, min)) / step) * step;
|
|
31
|
+
value = isNaN(tValue) ? Math.max(min, 0) : tValue;
|
|
32
|
+
dispatch("change", { value });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function input(e) {
|
|
37
|
+
dispatch("change", { value: e.target.value * 1, input: true });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const id = uid();
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<div
|
|
44
|
+
class="wx-counter"
|
|
45
|
+
class:wx-disabled={disabled}
|
|
46
|
+
class:wx-readonly={readonly}
|
|
47
|
+
class:wx-error={error}
|
|
48
|
+
>
|
|
49
|
+
<button class="wx-btn wx-btn-dec" {disabled} on:click={dec}>
|
|
50
|
+
<svg
|
|
51
|
+
class="wx-dec"
|
|
52
|
+
width="12"
|
|
53
|
+
height="2"
|
|
54
|
+
viewBox="0 0 12 2"
|
|
55
|
+
fill="none"
|
|
56
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
57
|
+
>
|
|
58
|
+
<path d="M11.2501 1.74994H0.750092V0.249939H11.2501V1.74994Z" />
|
|
59
|
+
</svg>
|
|
60
|
+
</button>
|
|
61
|
+
<input
|
|
62
|
+
{id}
|
|
63
|
+
type="text"
|
|
64
|
+
class="wx-input"
|
|
65
|
+
{disabled}
|
|
66
|
+
{readonly}
|
|
67
|
+
required
|
|
68
|
+
bind:value
|
|
69
|
+
on:blur={blur}
|
|
70
|
+
on:input={input}
|
|
71
|
+
/>
|
|
72
|
+
<button class="wx-btn wx-btn-inc" {disabled} on:click={inc}>
|
|
73
|
+
<svg
|
|
74
|
+
class="wx-inc"
|
|
75
|
+
width="12"
|
|
76
|
+
height="12"
|
|
77
|
+
viewBox="0 0 12 12"
|
|
78
|
+
fill="none"
|
|
79
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
80
|
+
>
|
|
81
|
+
<path
|
|
82
|
+
d="M11.2501
|
|
83
|
+
6.74994H6.75009V11.2499H5.25009V6.74994H0.750092V5.24994H5.25009V0.749939H6.75009V5.24994H11.2501V6.74994Z"
|
|
84
|
+
/>
|
|
85
|
+
</svg>
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<style>
|
|
90
|
+
.wx-counter {
|
|
91
|
+
display: flex;
|
|
92
|
+
border: var(--wx-input-border);
|
|
93
|
+
width: max-content;
|
|
94
|
+
border-radius: var(--wx-input-border-radius);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.wx-counter:not(.wx-readonly):has(.wx-input:focus) {
|
|
98
|
+
border: var(--wx-input-border-focus);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.wx-input {
|
|
102
|
+
box-sizing: border-box;
|
|
103
|
+
background: var(--wx-background);
|
|
104
|
+
width: 40px;
|
|
105
|
+
height: 30px;
|
|
106
|
+
font-family: var(--wx-input-font-family);
|
|
107
|
+
font-size: var(--wx-input-font-size);
|
|
108
|
+
color: var(--wx-input-font-color);
|
|
109
|
+
padding-left: 8px;
|
|
110
|
+
padding-right: 8px;
|
|
111
|
+
outline: none;
|
|
112
|
+
border: none;
|
|
113
|
+
border-left: var(--wx-input-border);
|
|
114
|
+
border-right: var(--wx-input-border);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.wx-btn {
|
|
118
|
+
box-sizing: border-box;
|
|
119
|
+
display: flex;
|
|
120
|
+
justify-content: center;
|
|
121
|
+
align-items: center;
|
|
122
|
+
width: 32px;
|
|
123
|
+
height: 30px;
|
|
124
|
+
font-family: var(--wx-input-font-family);
|
|
125
|
+
font-size: var(--wx-input-font-size);
|
|
126
|
+
color: var(--wx-input-font-color);
|
|
127
|
+
background-color: var(--wx-background-alt);
|
|
128
|
+
outline: none;
|
|
129
|
+
border: none;
|
|
130
|
+
cursor: pointer;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.wx-counter:not(.wx-readonly):not(.wx-disabled) .wx-btn:active {
|
|
134
|
+
background-color: var(--wx-background-hover);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.wx-dec,
|
|
138
|
+
.wx-inc {
|
|
139
|
+
fill: var(--wx-color-primary);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.wx-btn-dec {
|
|
143
|
+
border-radius: 2px 0 0 2px;
|
|
144
|
+
}
|
|
145
|
+
.wx-btn-inc {
|
|
146
|
+
border-radius: 0 2px 2px 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.wx-error,
|
|
150
|
+
.wx-counter.wx-error:has(.wx-input:focus) {
|
|
151
|
+
border: 1px solid var(--wx-color-danger);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.wx-error .wx-input {
|
|
155
|
+
color: var(--wx-color-danger);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.wx-disabled .wx-input,
|
|
159
|
+
.wx-disabled .wx-btn {
|
|
160
|
+
cursor: not-allowed;
|
|
161
|
+
color: var(--wx-color-font-disabled);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.wx-disabled .wx-btn {
|
|
165
|
+
background: var(--wx-color-disabled-alt);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.wx-disabled .wx-btn .wx-dec,
|
|
169
|
+
.wx-disabled .wx-btn .wx-inc,
|
|
170
|
+
.wx-readonly .wx-btn .wx-dec,
|
|
171
|
+
.wx-readonly .wx-btn .wx-inc {
|
|
172
|
+
fill: var(--wx-color-font-disabled);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.wx-readonly .wx-btn {
|
|
176
|
+
cursor: default;
|
|
177
|
+
}
|
|
178
|
+
</style>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext, createEventDispatcher } from "svelte";
|
|
3
|
+
import { uid, dateToString } from "wx-lib-dom";
|
|
4
|
+
|
|
5
|
+
import Text from "./Text.svelte";
|
|
6
|
+
import Dropdown from "./Dropdown.svelte";
|
|
7
|
+
import Calendar from "./Calendar.svelte";
|
|
8
|
+
|
|
9
|
+
export let value;
|
|
10
|
+
export let id = uid();
|
|
11
|
+
export let disabled = false;
|
|
12
|
+
export let error = false;
|
|
13
|
+
export let width = "unset";
|
|
14
|
+
export let align = "start";
|
|
15
|
+
export let placeholder = "";
|
|
16
|
+
export let format;
|
|
17
|
+
export let buttons = true;
|
|
18
|
+
export let css = "";
|
|
19
|
+
export let title = "";
|
|
20
|
+
export let editable = false;
|
|
21
|
+
|
|
22
|
+
const dispatch = createEventDispatcher();
|
|
23
|
+
|
|
24
|
+
const { calendar: calendarLocale, formats } =
|
|
25
|
+
getContext("wx-i18n").getRaw();
|
|
26
|
+
const f = format || formats.dateFormat;
|
|
27
|
+
let dateFormat =
|
|
28
|
+
typeof f === "function" ? f : dateToString(f, calendarLocale);
|
|
29
|
+
let popup;
|
|
30
|
+
|
|
31
|
+
function cancel() {
|
|
32
|
+
popup = false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function doChange(v) {
|
|
36
|
+
// skip "select" event if the same value
|
|
37
|
+
// or different objects with the same value
|
|
38
|
+
const skipEvent =
|
|
39
|
+
v === value ||
|
|
40
|
+
(v && value && v.valueOf() === value.valueOf()) ||
|
|
41
|
+
(!v && !value);
|
|
42
|
+
|
|
43
|
+
value = v;
|
|
44
|
+
if (!skipEvent) {
|
|
45
|
+
dispatch("select", { selected: v });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// fire after on-click finished
|
|
49
|
+
setTimeout(cancel, 1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let formattedValue;
|
|
53
|
+
$: formattedValue = value ? dateFormat(value) : "";
|
|
54
|
+
|
|
55
|
+
function doChangeInput(ev) {
|
|
56
|
+
if (!editable) return;
|
|
57
|
+
|
|
58
|
+
const { value: v, input } = ev.detail;
|
|
59
|
+
if (input) return;
|
|
60
|
+
|
|
61
|
+
// ensure that text in the input will be repainted
|
|
62
|
+
formattedValue = "";
|
|
63
|
+
|
|
64
|
+
// convert to date, but ignore empty string input
|
|
65
|
+
let date =
|
|
66
|
+
typeof editable === "function"
|
|
67
|
+
? editable(v)
|
|
68
|
+
: v
|
|
69
|
+
? new Date(v)
|
|
70
|
+
: null;
|
|
71
|
+
|
|
72
|
+
// if date is invalid ( incorrect text input ) then use old value
|
|
73
|
+
// else use the entered date
|
|
74
|
+
// in any case fallback to null, to prevent undefined as value
|
|
75
|
+
date = isNaN(date) ? value || null : date || null;
|
|
76
|
+
doChange(date);
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<svelte:window on:scroll={cancel} />
|
|
81
|
+
|
|
82
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
83
|
+
<div class="wx-datepicker" on:click={() => (popup = true)}>
|
|
84
|
+
<Text
|
|
85
|
+
{css}
|
|
86
|
+
{title}
|
|
87
|
+
value={formattedValue}
|
|
88
|
+
{id}
|
|
89
|
+
readonly={!editable}
|
|
90
|
+
{disabled}
|
|
91
|
+
{error}
|
|
92
|
+
{placeholder}
|
|
93
|
+
on:input={cancel}
|
|
94
|
+
on:change={doChangeInput}
|
|
95
|
+
icon="wxi-calendar"
|
|
96
|
+
inputStyle="cursor: pointer; width: 100%; padding-right: calc(var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2);"
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
{#if popup && !disabled}
|
|
100
|
+
<Dropdown {cancel} {width} {align} autoFit={!!align}>
|
|
101
|
+
<Calendar
|
|
102
|
+
{buttons}
|
|
103
|
+
{value}
|
|
104
|
+
on:change={e => doChange(e.detail.value)}
|
|
105
|
+
/>
|
|
106
|
+
</Dropdown>
|
|
107
|
+
{/if}
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<style>
|
|
111
|
+
.wx-datepicker {
|
|
112
|
+
position: relative;
|
|
113
|
+
width: var(--wx-input-width);
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext, createEventDispatcher } from "svelte";
|
|
3
|
+
import { uid, dateToString } from "wx-lib-dom";
|
|
4
|
+
|
|
5
|
+
import Text from "./Text.svelte";
|
|
6
|
+
import Dropdown from "./Dropdown.svelte";
|
|
7
|
+
import RangeCalendar from "./RangeCalendar.svelte";
|
|
8
|
+
|
|
9
|
+
export let value;
|
|
10
|
+
export let id = uid();
|
|
11
|
+
export let disabled = false;
|
|
12
|
+
export let error = false;
|
|
13
|
+
export let done = false;
|
|
14
|
+
export let width = "unset";
|
|
15
|
+
export let align = "start";
|
|
16
|
+
export let placeholder = "";
|
|
17
|
+
export let css;
|
|
18
|
+
export let title;
|
|
19
|
+
export let format;
|
|
20
|
+
export let months = 2;
|
|
21
|
+
export let buttons;
|
|
22
|
+
export let editable = false;
|
|
23
|
+
|
|
24
|
+
const dispatch = createEventDispatcher();
|
|
25
|
+
|
|
26
|
+
const { calendar: calendarLocale, formats } =
|
|
27
|
+
getContext("wx-i18n").getRaw();
|
|
28
|
+
const f = format || formats?.dateFormat;
|
|
29
|
+
let dateFormat =
|
|
30
|
+
typeof f === "function" ? f : dateToString(f, calendarLocale);
|
|
31
|
+
let popup;
|
|
32
|
+
|
|
33
|
+
function cancel() {
|
|
34
|
+
popup = false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let formattedValue;
|
|
38
|
+
$: formattedValue = value
|
|
39
|
+
? value.start
|
|
40
|
+
? dateFormat(value.start) +
|
|
41
|
+
(value.end ? ` - ${dateFormat(value.end)}` : "")
|
|
42
|
+
: dateFormat(value)
|
|
43
|
+
: "";
|
|
44
|
+
|
|
45
|
+
function doChange(d) {
|
|
46
|
+
value = d.start || d.end ? { start: d.start, end: d.end } : null;
|
|
47
|
+
|
|
48
|
+
// fire after on-click finished
|
|
49
|
+
if ((d.start && d.end) || (!d.start && !d.end)) {
|
|
50
|
+
// FIXME - select event will trigger even if the same value
|
|
51
|
+
dispatch("select", { selected: value });
|
|
52
|
+
setTimeout(cancel, 1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function doInputChange(ev) {
|
|
57
|
+
if (!editable) return;
|
|
58
|
+
|
|
59
|
+
const { value: v, input } = ev.detail;
|
|
60
|
+
if (input) return;
|
|
61
|
+
|
|
62
|
+
// reset formatted value to ensure that text in the input will be repainted
|
|
63
|
+
formattedValue = "";
|
|
64
|
+
|
|
65
|
+
const [s, e] = v.split(" -").map((a, i) => {
|
|
66
|
+
const av = a.trim();
|
|
67
|
+
let date =
|
|
68
|
+
typeof editable === "function"
|
|
69
|
+
? editable(av)
|
|
70
|
+
: av
|
|
71
|
+
? new Date(av)
|
|
72
|
+
: null;
|
|
73
|
+
|
|
74
|
+
// if date is invalid ( incorrect text input ) then use old value
|
|
75
|
+
// else use the entered date
|
|
76
|
+
// in any case fallback to null, to prevent undefined as value
|
|
77
|
+
let value = i === 0 ? start : end;
|
|
78
|
+
return isNaN(date) ? (value ? value : null) : date || null;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
doChange({ start: s, end: e });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let start, end;
|
|
85
|
+
$: {
|
|
86
|
+
if (!value) {
|
|
87
|
+
start = end = null;
|
|
88
|
+
} else {
|
|
89
|
+
start = value.start || null;
|
|
90
|
+
end = value.end || null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<svelte:window on:scroll={cancel} />
|
|
96
|
+
|
|
97
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
98
|
+
<div
|
|
99
|
+
class="wx-daterangepicker"
|
|
100
|
+
class:wx-disabled={disabled}
|
|
101
|
+
class:wx-error={error}
|
|
102
|
+
on:click={() => (popup = true)}
|
|
103
|
+
>
|
|
104
|
+
<Text
|
|
105
|
+
{css}
|
|
106
|
+
{title}
|
|
107
|
+
value={formattedValue}
|
|
108
|
+
{id}
|
|
109
|
+
readonly={!editable}
|
|
110
|
+
{disabled}
|
|
111
|
+
{placeholder}
|
|
112
|
+
{error}
|
|
113
|
+
on:change={doInputChange}
|
|
114
|
+
icon="wxi-calendar"
|
|
115
|
+
inputStyle="cursor: pointer; width: 100%; padding-right: calc(var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2);"
|
|
116
|
+
/>
|
|
117
|
+
|
|
118
|
+
{#if popup && !disabled}
|
|
119
|
+
<Dropdown {cancel} {width} {align} autoFit={!!align}>
|
|
120
|
+
<RangeCalendar
|
|
121
|
+
{done}
|
|
122
|
+
{cancel}
|
|
123
|
+
{buttons}
|
|
124
|
+
{start}
|
|
125
|
+
{end}
|
|
126
|
+
{months}
|
|
127
|
+
on:change={e => doChange(e.detail)}
|
|
128
|
+
/>
|
|
129
|
+
</Dropdown>
|
|
130
|
+
{/if}
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<style>
|
|
134
|
+
.wx-daterangepicker {
|
|
135
|
+
position: relative;
|
|
136
|
+
width: var(--wx-input-width);
|
|
137
|
+
}
|
|
138
|
+
</style>
|