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.
Files changed (60) hide show
  1. package/license.txt +21 -0
  2. package/package.json +35 -0
  3. package/src/Locale.svelte +17 -0
  4. package/src/components/Area.svelte +70 -0
  5. package/src/components/Button.svelte +187 -0
  6. package/src/components/Calendar.svelte +42 -0
  7. package/src/components/Checkbox.svelte +132 -0
  8. package/src/components/CheckboxGroup.svelte +52 -0
  9. package/src/components/ColorBoard.svelte +311 -0
  10. package/src/components/ColorPicker.svelte +110 -0
  11. package/src/components/ColorSelect.svelte +204 -0
  12. package/src/components/Combo.svelte +228 -0
  13. package/src/components/Counter.svelte +178 -0
  14. package/src/components/DatePicker.svelte +115 -0
  15. package/src/components/DateRangePicker.svelte +138 -0
  16. package/src/components/Dropdown.svelte +125 -0
  17. package/src/components/Field.svelte +91 -0
  18. package/src/components/Globals.svelte +53 -0
  19. package/src/components/Icon.svelte +31 -0
  20. package/src/components/Modal.svelte +115 -0
  21. package/src/components/ModalArea.svelte +32 -0
  22. package/src/components/MultiCombo.svelte +279 -0
  23. package/src/components/Notice.svelte +145 -0
  24. package/src/components/Notices.svelte +20 -0
  25. package/src/components/Pager.svelte +131 -0
  26. package/src/components/Popup.svelte +53 -0
  27. package/src/components/Portal.svelte +42 -0
  28. package/src/components/RadioButton.svelte +129 -0
  29. package/src/components/RadioButtonGroup.svelte +50 -0
  30. package/src/components/RangeCalendar.svelte +134 -0
  31. package/src/components/RichSelect.svelte +149 -0
  32. package/src/components/Segmented.svelte +115 -0
  33. package/src/components/Select.svelte +124 -0
  34. package/src/components/SideArea.svelte +33 -0
  35. package/src/components/Slider.svelte +242 -0
  36. package/src/components/Switch.svelte +88 -0
  37. package/src/components/Tabs.svelte +163 -0
  38. package/src/components/Text.svelte +185 -0
  39. package/src/components/Timepicker.svelte +217 -0
  40. package/src/components/TwoState.svelte +60 -0
  41. package/src/components/calendar/Button.svelte +40 -0
  42. package/src/components/calendar/Duodecade.svelte +97 -0
  43. package/src/components/calendar/Header.svelte +105 -0
  44. package/src/components/calendar/Month.svelte +189 -0
  45. package/src/components/calendar/Panel.svelte +119 -0
  46. package/src/components/calendar/Year.svelte +89 -0
  47. package/src/components/calendar/helpers.js +56 -0
  48. package/src/components/helpers/SuggestDropdown.svelte +79 -0
  49. package/src/components/helpers/colorTransformator.js +146 -0
  50. package/src/components/helpers/colorValidation.js +21 -0
  51. package/src/components/helpers/listnav.js +85 -0
  52. package/src/components/helpers/sliderMove.js +42 -0
  53. package/src/components/helpers.js +6 -0
  54. package/src/index.js +50 -0
  55. package/src/themes/FontOpenSans.svelte +36 -0
  56. package/src/themes/FonttRoboto.svelte +19 -0
  57. package/src/themes/Material.svelte +321 -0
  58. package/src/themes/Willow.svelte +323 -0
  59. package/src/themes/WillowDark.svelte +320 -0
  60. 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>