wx-svelte-core 2.0.0-beta-2 → 2.0.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 (35) hide show
  1. package/package.json +12 -3
  2. package/src/components/Checkbox.svelte +3 -3
  3. package/src/components/CheckboxGroup.svelte +7 -6
  4. package/src/components/ColorBoard.svelte +6 -2
  5. package/src/components/ColorPicker.svelte +40 -2
  6. package/src/components/ColorSelect.svelte +11 -8
  7. package/src/components/Combo.svelte +11 -7
  8. package/src/components/DatePicker.svelte +9 -7
  9. package/src/components/DateRangePicker.svelte +9 -7
  10. package/src/components/Dropdown.svelte +2 -2
  11. package/src/components/Globals.svelte +2 -2
  12. package/src/components/Modal.svelte +17 -8
  13. package/src/components/MultiCombo.svelte +18 -30
  14. package/src/components/Notice.svelte +10 -10
  15. package/src/components/Popup.svelte +2 -2
  16. package/src/components/RadioButton.svelte +7 -6
  17. package/src/components/RadioButtonGroup.svelte +14 -4
  18. package/src/components/RichSelect.svelte +24 -6
  19. package/src/components/Segmented.svelte +4 -4
  20. package/src/components/Select.svelte +35 -4
  21. package/src/components/SideArea.svelte +2 -2
  22. package/src/components/Slider.svelte +3 -4
  23. package/src/components/Switch.svelte +7 -1
  24. package/src/components/Text.svelte +38 -7
  25. package/src/components/{Timepicker.svelte → TimePicker.svelte} +6 -2
  26. package/src/components/TwoState.svelte +5 -1
  27. package/src/components/calendar/Duodecade.svelte +1 -1
  28. package/src/components/helpers/SuggestDropdown.svelte +6 -4
  29. package/src/components/helpers/listnav.js +3 -2
  30. package/src/index.js +6 -4
  31. package/src/themes/Material.svelte +1 -0
  32. package/src/themes/Willow.svelte +1 -0
  33. package/src/themes/WillowDark.svelte +1 -0
  34. package/whatsnew.md +11 -0
  35. /package/src/components/{Area.svelte → TextArea.svelte} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wx-svelte-core",
3
- "version": "2.0.0-beta-2",
3
+ "version": "2.0.0",
4
4
  "description": "SVAR Svelte Core library, a collection of form controls and UI components",
5
5
  "productTag": "core",
6
6
  "productTrial": false,
@@ -23,9 +23,18 @@
23
23
  "./package.json": "./package.json"
24
24
  },
25
25
  "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/svar-widgets/core.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://forum.svar.dev"
32
+ },
33
+ "homepage": "https://svar.dev/svelte/core/",
26
34
  "dependencies": {
27
- "wx-core-locales": "2.0.0-beta-2",
28
- "wx-lib-dom": "0.6.0"
35
+ "wx-core-locales": "2.0.0",
36
+ "wx-lib-dom": "0.7.0",
37
+ "wx-lib-svelte": "0.5.0"
29
38
  },
30
39
  "files": [
31
40
  "src",
@@ -4,7 +4,7 @@
4
4
  let {
5
5
  id = uid(),
6
6
  label = "",
7
- name = "",
7
+ inputValue = "",
8
8
  value = $bindable(false),
9
9
  style = "",
10
10
  disabled = false,
@@ -13,7 +13,7 @@
13
13
 
14
14
  function handlerChange({ target }) {
15
15
  value = target.checked;
16
- onchange && onchange({ value, name });
16
+ onchange && onchange({ value, inputValue });
17
17
  }
18
18
  </script>
19
19
 
@@ -23,7 +23,7 @@
23
23
  {id}
24
24
  {disabled}
25
25
  checked={value}
26
- value={name}
26
+ value={inputValue}
27
27
  onchange={handlerChange}
28
28
  />
29
29
  <label for={id}>
@@ -1,11 +1,12 @@
1
1
  <script>
2
2
  import Checkbox from "./Checkbox.svelte";
3
3
 
4
- let { options = [], value = $bindable([]), type = "" } = $props();
4
+ let { options = [], value = $bindable([]), type = "", onchange } = $props();
5
5
 
6
6
  function handleChange(obj) {
7
- if (obj.value) value = [...value, obj.name];
8
- else value = value.filter(a => a != obj.name);
7
+ if (obj.value) value = [...value, obj.inputValue];
8
+ else value = value.filter(a => a != obj.inputValue);
9
+ onchange && onchange({ value });
9
10
  }
10
11
  </script>
11
12
 
@@ -14,8 +15,8 @@
14
15
  <div class="wx-item">
15
16
  <Checkbox
16
17
  label={option.label}
17
- name={option.value}
18
- value={value.includes(option.value)}
18
+ inputValue={option.id}
19
+ value={value.includes(option.id)}
19
20
  onchange={handleChange}
20
21
  />
21
22
  </div>
@@ -41,7 +42,7 @@
41
42
  padding-right: var(--wx-field-gutter);
42
43
  }
43
44
 
44
- .wx-checkboxgroup.grid .wx-item {
45
+ .wx-checkboxgroup.wx-grid .wx-item {
45
46
  flex: 0 0 50%;
46
47
  max-width: 50%;
47
48
  padding-right: var(--wx-field-gutter);
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { onMount } from "svelte";
2
+ import { onMount, getContext } from "svelte";
3
3
  import Button from "./Button.svelte";
4
4
 
5
5
  //helpers
@@ -11,6 +11,8 @@
11
11
 
12
12
  let block;
13
13
 
14
+ const _ = getContext("wx-i18n").getGroup("core");
15
+
14
16
  const BLOCK = "Block";
15
17
  const LINE = "Line";
16
18
 
@@ -54,6 +56,7 @@
54
56
  }
55
57
 
56
58
  value = colorTransformator.hvsToHex(hueColor, _sValue, _vValue);
59
+ onchange && onchange({ value, input: true });
57
60
  }
58
61
 
59
62
  function moveLineSlider(dx) {
@@ -92,6 +95,7 @@
92
95
  const newColor = parseColor(target.value);
93
96
 
94
97
  value = newColor;
98
+ onchange && onchange({ value, input: true });
95
99
  if (newColor) {
96
100
  setSlidersPosition();
97
101
  }
@@ -185,7 +189,7 @@
185
189
  <input type="text" class="wx-text" bind:value onchange={handleChange} />
186
190
  </div>
187
191
  {#if button}
188
- <Button onclick={handleSelect} type="secondary">Select</Button>
192
+ <Button onclick={handleSelect} type="secondary">{_("select")}</Button>
189
193
  {/if}
190
194
  </div>
191
195
 
@@ -10,6 +10,7 @@
10
10
  title = "",
11
11
  disabled = false,
12
12
  error = false,
13
+ clear = false,
13
14
  onchange,
14
15
  } = $props();
15
16
 
@@ -20,8 +21,17 @@
20
21
  popup = true;
21
22
  }
22
23
 
23
- function selectColor({ value }) {
24
+ function selectColor(ev) {
25
+ if (ev.input) return;
26
+
24
27
  popup = false;
28
+ value = ev.value;
29
+ onchange && onchange({ value });
30
+ }
31
+
32
+ function unselectColor(ev) {
33
+ ev.stopPropagation();
34
+ value = "";
25
35
  onchange && onchange({ value });
26
36
  }
27
37
  </script>
@@ -41,8 +51,12 @@
41
51
  />
42
52
  <div class="wx-color" style="background: {value}"></div>
43
53
 
54
+ {#if clear && !disabled && value}
55
+ <i class="wxi-close" onclick={unselectColor}></i>
56
+ {/if}
57
+
44
58
  {#if popup}
45
- <Dropdown cancel={() => (popup = false)}>
59
+ <Dropdown oncancel={() => (popup = false)}>
46
60
  <ColorBoard {value} button="true" onchange={selectColor} />
47
61
  </Dropdown>
48
62
  {/if}
@@ -111,4 +125,28 @@
111
125
  border-color: var(--wx-color-danger);
112
126
  color: var(--wx-color-danger);
113
127
  }
128
+
129
+ .wxi-close {
130
+ position: absolute;
131
+ right: var(--wx-input-icon-indent);
132
+ top: 50%;
133
+ transform: translateY(-50%);
134
+ font-size: var(--wx-input-icon-size);
135
+ line-height: 1;
136
+ width: var(--wx-input-icon-size);
137
+ height: var(--wx-input-icon-size);
138
+ display: flex;
139
+ justify-content: center;
140
+ align-items: center;
141
+ user-select: none;
142
+ color: var(--wx-input-icon-color);
143
+ cursor: pointer;
144
+ }
145
+ .wxi-close:before {
146
+ display: block;
147
+ }
148
+ .wxi-close:hover {
149
+ background: var(--wx-background-hover);
150
+ border-radius: var(--wx-icon-border-radius);
151
+ }
114
152
  </style>
@@ -16,24 +16,26 @@
16
16
  colors = defaultColors,
17
17
  value = $bindable(""),
18
18
  id = uid(),
19
- clear = true,
19
+ clear = false,
20
20
  placeholder = "",
21
21
  title = "",
22
22
  disabled = false,
23
23
  error = false,
24
+ onchange,
24
25
  } = $props();
25
26
 
26
27
  let popup = $state(false);
27
28
 
28
29
  function selectColor(ev, color) {
29
30
  ev.stopPropagation();
30
-
31
31
  value = color;
32
32
  popup = false;
33
+ onchange && onchange({ value });
33
34
  }
34
- function handleClear(ev) {
35
+ function unselectColor(ev) {
35
36
  ev.stopPropagation();
36
- value = null;
37
+ value = "";
38
+ onchange && onchange({ value });
37
39
  }
38
40
  function handlePopup() {
39
41
  if (disabled) return false;
@@ -58,7 +60,7 @@
58
60
  {#if clear && value && !disabled}
59
61
  <!-- svelte-ignore a11y_click_events_have_key_events -->
60
62
  <!-- svelte-ignore a11y_no_static_element_interactions -->
61
- <i class="wx-clear wxi-close" onclick={handleClear}></i>
63
+ <i class="wx-clear wxi-close" onclick={unselectColor}></i>
62
64
  {/if}
63
65
 
64
66
  {#if value}
@@ -71,7 +73,7 @@
71
73
  {/if}
72
74
 
73
75
  {#if popup}
74
- <Dropdown cancel={() => (popup = false)}>
76
+ <Dropdown oncancel={() => (popup = false)}>
75
77
  <div class="wx-colors">
76
78
  <!-- svelte-ignore a11y_click_events_have_key_events -->
77
79
  <!-- svelte-ignore a11y_no_static_element_interactions -->
@@ -182,7 +184,7 @@
182
184
  user-select: none;
183
185
  }
184
186
 
185
- .wx-clear {
187
+ .wxi-close {
186
188
  position: absolute;
187
189
  right: var(--wx-input-icon-indent);
188
190
  top: 50%;
@@ -198,7 +200,8 @@
198
200
  color: var(--wx-input-icon-color);
199
201
  cursor: pointer;
200
202
  }
201
- .wx-clear:hover {
203
+ .wxi-close:hover {
202
204
  background: var(--wx-background-hover);
205
+ border-radius: var(--wx-icon-border-radius);
203
206
  }
204
207
  </style>
@@ -11,7 +11,7 @@
11
11
  title = "",
12
12
  disabled = false,
13
13
  error = false,
14
- clearButton = false,
14
+ clear = false,
15
15
  children: kids,
16
16
  onchange,
17
17
  } = $props();
@@ -50,7 +50,7 @@
50
50
 
51
51
  function selectByText(chunk) {
52
52
  if (!options.length) return;
53
- if (chunk === "" && clearButton) {
53
+ if (chunk === "" && clear) {
54
54
  doUnselect();
55
55
  return;
56
56
  }
@@ -75,7 +75,7 @@
75
75
 
76
76
  if (value !== selected.id) {
77
77
  value = selected.id;
78
- onchange && onchange({ value: selected });
78
+ onchange && onchange({ value });
79
79
  }
80
80
  }
81
81
 
@@ -87,7 +87,7 @@
87
87
 
88
88
  value = "";
89
89
  filterActive = false;
90
- onchange && onchange({ value: null });
90
+ onchange && onchange({ value });
91
91
  }
92
92
 
93
93
  function oninput() {
@@ -124,7 +124,7 @@
124
124
  {oninput}
125
125
  />
126
126
 
127
- {#if clearButton && !disabled && value}
127
+ {#if clear && !disabled && value}
128
128
  <!-- svelte-ignore a11y_click_events_have_key_events -->
129
129
  <!-- svelte-ignore a11y_no_static_element_interactions -->
130
130
  <i class="wx-icon wxi-close" onclick={doUnselect}></i>
@@ -133,7 +133,9 @@
133
133
  {#if !disabled}
134
134
  <List items={filteredOptions} onready={ready} onselect={selectByEvent}>
135
135
  {#snippet children({ option })}
136
- {#if kids}{@render kids({ option })}{:else}{option.name}{/if}
136
+ {#if kids}{@render kids({ option })}{:else}{option[
137
+ textField
138
+ ]}{/if}
137
139
  {/snippet}
138
140
  </List>
139
141
  {/if}
@@ -215,9 +217,11 @@
215
217
 
216
218
  .wx-icon.wxi-close {
217
219
  pointer-events: all;
220
+ cursor: pointer;
218
221
  }
219
222
 
220
223
  .wx-icon.wxi-close:hover {
221
- color: var(--wx-color-danger);
224
+ background: var(--wx-background-hover);
225
+ border-radius: var(--wx-icon-border-radius);
222
226
  }
223
227
  </style>
@@ -19,6 +19,7 @@
19
19
  css = "",
20
20
  title = "",
21
21
  editable = false,
22
+ clear = false,
22
23
  onchange: change,
23
24
  } = $props();
24
25
 
@@ -30,7 +31,7 @@
30
31
 
31
32
  let popup = $state();
32
33
 
33
- function cancel() {
34
+ function oncancel() {
34
35
  popup = false;
35
36
  }
36
37
 
@@ -44,17 +45,17 @@
44
45
 
45
46
  value = v;
46
47
  if (!skipEvent) {
47
- change && change({ selected: v });
48
+ change && change({ value });
48
49
  }
49
50
 
50
51
  // fire after on-click finished
51
- setTimeout(cancel, 1);
52
+ setTimeout(oncancel, 1);
52
53
  }
53
54
 
54
55
  const formattedValue = $derived(value ? dateFormat(value) : "");
55
56
 
56
57
  function onchange({ value: v, input }) {
57
- if (!editable) return;
58
+ if (!editable && !clear) return;
58
59
  if (input) return;
59
60
 
60
61
  // convert to date, but ignore empty string input
@@ -73,7 +74,7 @@
73
74
  }
74
75
  </script>
75
76
 
76
- <svelte:window onscroll={cancel} />
77
+ <svelte:window onscroll={oncancel} />
77
78
 
78
79
  <!-- svelte-ignore a11y_click_events_have_key_events -->
79
80
  <!-- svelte-ignore a11y_no_static_element_interactions -->
@@ -87,14 +88,15 @@
87
88
  {disabled}
88
89
  {error}
89
90
  {placeholder}
90
- oninput={cancel}
91
+ oninput={oncancel}
91
92
  {onchange}
92
93
  icon="wxi-calendar"
93
94
  inputStyle="cursor: pointer; width: 100%; padding-right: calc(var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2);"
95
+ {clear}
94
96
  />
95
97
 
96
98
  {#if popup && !disabled}
97
- <Dropdown {cancel} {width} {align} autoFit={!!align}>
99
+ <Dropdown {oncancel} {width} {align} autoFit={!!align}>
98
100
  <Calendar {buttons} {value} onchange={e => doChange(e.value)} />
99
101
  </Dropdown>
100
102
  {/if}
@@ -21,6 +21,7 @@
21
21
  months = 2,
22
22
  buttons = true,
23
23
  editable = false,
24
+ clear = false,
24
25
  onchange,
25
26
  } = $props();
26
27
 
@@ -31,7 +32,7 @@
31
32
  typeof f === "function" ? f : dateToString(f, calendarLocale);
32
33
  let popup = $state();
33
34
 
34
- function cancel() {
35
+ function oncancel() {
35
36
  popup = false;
36
37
  }
37
38
 
@@ -50,13 +51,13 @@
50
51
  // fire after on-click finished
51
52
  if ((d.start && d.end) || (!d.start && !d.end)) {
52
53
  // FIXME - select event will trigger even if the same value
53
- onchange && onchange({ selected: value });
54
- setTimeout(cancel, 1);
54
+ onchange && onchange({ value });
55
+ setTimeout(oncancel, 1);
55
56
  }
56
57
  }
57
58
 
58
59
  function doInputChange(ev) {
59
- if (!editable) return;
60
+ if (!editable && !clear) return;
60
61
 
61
62
  const { value: v, input } = ev;
62
63
  if (input) return;
@@ -84,7 +85,7 @@
84
85
  const end = $derived(value ? value.end || null : null);
85
86
  </script>
86
87
 
87
- <svelte:window onscroll={cancel} />
88
+ <svelte:window onscroll={oncancel} />
88
89
 
89
90
  <!-- svelte-ignore a11y_click_events_have_key_events -->
90
91
  <!-- svelte-ignore a11y_no_static_element_interactions -->
@@ -106,13 +107,14 @@
106
107
  onchange={doInputChange}
107
108
  icon="wxi-calendar"
108
109
  inputStyle="cursor: pointer; width: 100%; padding-right: calc(var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2);"
110
+ {clear}
109
111
  />
110
112
 
111
113
  {#if popup && !disabled}
112
- <Dropdown {cancel} {width} {align} autoFit={!!align}>
114
+ <Dropdown {oncancel} {width} {align} autoFit={!!align}>
113
115
  <RangeCalendar
114
116
  {done}
115
- {cancel}
117
+ {oncancel}
116
118
  {buttons}
117
119
  {start}
118
120
  {end}
@@ -5,7 +5,7 @@
5
5
  position = "bottom",
6
6
  align = "start",
7
7
  autoFit = true,
8
- cancel = null,
8
+ oncancel = null,
9
9
  width = "100%",
10
10
  children,
11
11
  } = $props();
@@ -28,7 +28,7 @@
28
28
  });
29
29
 
30
30
  function down(e) {
31
- if (cancel) cancel(e);
31
+ oncancel && oncancel(e);
32
32
  }
33
33
  </script>
34
34
 
@@ -46,8 +46,8 @@
46
46
  <Modal
47
47
  title={modal.title}
48
48
  buttons={modal.buttons}
49
- ok={modal.resolve}
50
- cancel={modal.reject}
49
+ onconfirm={modal.resolve}
50
+ oncancel={modal.reject}
51
51
  >
52
52
  {modal.message}
53
53
  </Modal>
@@ -7,28 +7,37 @@
7
7
 
8
8
  const {
9
9
  title = "",
10
- ok,
11
- cancel,
12
10
  buttons = ["cancel", "ok"],
13
11
  header,
14
12
  children,
15
13
  footer,
14
+ onconfirm,
15
+ oncancel,
16
16
  } = $props();
17
17
 
18
- function keydown(e) {
19
- switch (e.code) {
18
+ function keydown(ev) {
19
+ switch (ev.code) {
20
20
  case "Enter": {
21
- const from = e.target.tagName;
21
+ const from = ev.target.tagName;
22
22
  if (from === "TEXTAREA" || from === "BUTTON") return;
23
- ok();
23
+ onconfirm && onconfirm({ ev });
24
24
  break;
25
25
  }
26
26
  case "Escape":
27
- cancel();
27
+ oncancel && oncancel({ ev });
28
28
  break;
29
29
  }
30
30
  }
31
31
 
32
+ function onclick(ev, button) {
33
+ const pack = { ev, button };
34
+ if (button === "cancel") {
35
+ oncancel && oncancel(pack);
36
+ } else {
37
+ onconfirm && onconfirm(pack);
38
+ }
39
+ }
40
+
32
41
  let modal;
33
42
  onMount(() => {
34
43
  modal.focus();
@@ -63,7 +72,7 @@
63
72
  type="block {button === 'ok'
64
73
  ? 'primary'
65
74
  : 'secondary'}"
66
- onclick={() => (button === "ok" ? ok() : cancel())}
75
+ onclick={ev => onclick(ev, button)}
67
76
  >
68
77
  {_(button)}
69
78
  </Button>
@@ -14,7 +14,6 @@
14
14
  error = false,
15
15
  checkboxes = false,
16
16
  onchange: change,
17
- onselect: select,
18
17
  children,
19
18
  } = $props();
20
19
 
@@ -58,7 +57,6 @@
58
57
  }
59
58
 
60
59
  value = next;
61
- select && select({ selected });
62
60
  change && change({ value });
63
61
  }
64
62
  }
@@ -97,7 +95,9 @@
97
95
  {#if !disabled}
98
96
  <!-- svelte-ignore a11y_click_events_have_key_events -->
99
97
  <!-- svelte-ignore a11y_no_static_element_interactions -->
100
- <i class="wxi-close" onclick={ev => remove(tag.id, ev)}
98
+ <i
99
+ class="wx-icon wxi-close"
100
+ onclick={ev => remove(tag.id, ev)}
101
101
  ></i>
102
102
  {/if}
103
103
  </div>
@@ -128,7 +128,7 @@
128
128
  {/if}
129
129
  {#if children}{@render children({
130
130
  option,
131
- })}{:else}{option.name}{/if}
131
+ })}{:else}{option[textField]}{/if}
132
132
  {/snippet}
133
133
  </List>
134
134
  {/if}
@@ -159,7 +159,7 @@
159
159
  cursor: not-allowed;
160
160
  color: var(--wx-color-font-disabled);
161
161
  }
162
- .wx-multicombo.wx-disabled .wx-icon {
162
+ .wx-multicombo.wx-disabled .wx-icon.wxi-angle-down {
163
163
  color: var(--wx-color-font-disabled);
164
164
  }
165
165
  .wx-multicombo.wx-error .wx-wrapper {
@@ -168,7 +168,7 @@
168
168
  .wx-multicombo.wx-error input {
169
169
  color: var(--wx-color-danger);
170
170
  }
171
- .wx-multicombo.wx-error .wx-icon {
171
+ .wx-multicombo.wx-error .wx-icon.wxi-angle-down {
172
172
  color: var(--wx-color-danger);
173
173
  }
174
174
  .wx-multicombo.wx-not-empty .wx-tags {
@@ -214,8 +214,7 @@
214
214
  background: var(--wx-multicombo-tag-background);
215
215
  padding: var(--wx-multicombo-tag-pading);
216
216
  }
217
-
218
- .wxi-close {
217
+ .wx-icon {
219
218
  position: absolute;
220
219
  right: var(--wx-input-icon-indent);
221
220
  top: 50%;
@@ -227,12 +226,21 @@
227
226
  align-items: center;
228
227
  width: var(--wx-input-icon-size);
229
228
  height: var(--wx-input-icon-size);
230
- border-radius: var(--wx-input-border-radius);
229
+ pointer-events: none;
230
+ user-select: none;
231
231
  color: var(--wx-input-icon-color);
232
+ }
233
+ .wx-icon:before {
234
+ display: block;
235
+ }
236
+
237
+ .wxi-close {
238
+ pointer-events: all;
232
239
  cursor: pointer;
233
240
  }
234
241
  .wxi-close:hover {
235
- color: var(--wx-color-primary);
242
+ background: var(--wx-background-hover);
243
+ border-radius: var(--wx-icon-border-radius);
236
244
  }
237
245
 
238
246
  .wx-select {
@@ -261,24 +269,4 @@
261
269
  text-overflow: ellipsis;
262
270
  cursor: pointer;
263
271
  }
264
-
265
- .wx-icon {
266
- position: absolute;
267
- right: var(--wx-input-icon-indent);
268
- top: 50%;
269
- transform: translateY(-50%);
270
- font-size: var(--wx-input-icon-size);
271
- line-height: 1;
272
- width: var(--wx-input-icon-size);
273
- height: var(--wx-input-icon-size);
274
- display: flex;
275
- justify-content: center;
276
- align-items: center;
277
- pointer-events: none;
278
- user-select: none;
279
- color: var(--wx-input-icon-color);
280
- }
281
- .wx-icon:before {
282
- display: block;
283
- }
284
272
  </style>
@@ -17,7 +17,7 @@
17
17
  <div class="wx-button">
18
18
  <!-- svelte-ignore a11y_click_events_have_key_events -->
19
19
  <!-- svelte-ignore a11y_no_static_element_interactions -->
20
- <i class="wx-close wxi-close" onclick={onRemove}></i>
20
+ <i class="wxi-close" onclick={onRemove}></i>
21
21
  </div>
22
22
  </div>
23
23
 
@@ -82,7 +82,7 @@
82
82
  );
83
83
  }
84
84
 
85
- .wx-close {
85
+ .wxi-close {
86
86
  position: relative;
87
87
  display: flex;
88
88
  justify-content: center;
@@ -94,11 +94,11 @@
94
94
  color: var(--wx-notice-type-icon-color);
95
95
  cursor: pointer;
96
96
  }
97
- .wx-close:before {
97
+ .wxi-close:before {
98
98
  display: block;
99
99
  z-index: 1;
100
100
  }
101
- .wx-close:after {
101
+ .wxi-close:after {
102
102
  content: "";
103
103
  display: block;
104
104
  position: absolute;
@@ -107,9 +107,9 @@
107
107
  transform: translate(-50%, -50%);
108
108
  width: calc(100% + 4px);
109
109
  height: calc(100% + 4px);
110
- border-radius: 50%;
110
+ border-radius: var(--wx-icon-border-radius);
111
111
  }
112
- .wx-close:hover:after {
112
+ .wxi-close:hover:after {
113
113
  background: var(--wx-background-hover);
114
114
  }
115
115
 
@@ -137,10 +137,10 @@
137
137
  background: var(--wx-color-danger);
138
138
  }
139
139
 
140
- .wx-notice.wx-info .wx-close:after,
141
- .wx-notice.wx-warning .wx-close:after,
142
- .wx-notice.wx-success .wx-close:after,
143
- .wx-notice.wx-danger .wx-close:after {
140
+ .wx-notice.wx-info .wxi-close:after,
141
+ .wx-notice.wx-warning .wxi-close:after,
142
+ .wx-notice.wx-success .wxi-close:after,
143
+ .wx-notice.wx-danger .wxi-close:after {
144
144
  opacity: var(--wx-notice-type-close-hover-opacity);
145
145
  }
146
146
  </style>
@@ -7,7 +7,7 @@
7
7
  top = 0,
8
8
  at = "bottom",
9
9
  parent = null,
10
- cancel,
10
+ oncancel,
11
11
  mount,
12
12
  children,
13
13
  } = $props();
@@ -33,7 +33,7 @@
33
33
  });
34
34
 
35
35
  function down(e) {
36
- if (cancel) cancel(e);
36
+ oncancel && oncancel(e);
37
37
  }
38
38
  </script>
39
39
 
@@ -4,15 +4,16 @@
4
4
  let {
5
5
  id = uid(),
6
6
  label = "",
7
- value = "",
8
- groupValue = $bindable(""),
7
+ value = $bindable(""),
9
8
  name = "",
9
+ inputValue = "",
10
10
  disabled = false,
11
- checked = false,
11
+ onchange,
12
12
  } = $props();
13
13
 
14
14
  function handlerChange(ev) {
15
- if (ev.target.checked) groupValue = value;
15
+ value = ev.target.checked;
16
+ if (value) onchange && onchange({ value: true, inputValue });
16
17
  }
17
18
  </script>
18
19
 
@@ -20,10 +21,10 @@
20
21
  <input
21
22
  type="radio"
22
23
  {id}
23
- {value}
24
24
  {disabled}
25
25
  {name}
26
- {checked}
26
+ value={inputValue}
27
+ checked={value}
27
28
  onchange={handlerChange}
28
29
  />
29
30
  <label for={id}>
@@ -2,9 +2,19 @@
2
2
  import { uid } from "wx-lib-dom";
3
3
  import RadioButton from "./RadioButton.svelte";
4
4
 
5
- let { options = [{}], value = $bindable(""), type = "" } = $props();
5
+ let {
6
+ options = [{}],
7
+ value = $bindable(""),
8
+ type = "",
9
+ onchange,
10
+ } = $props();
6
11
 
7
12
  const name = uid();
13
+
14
+ function handleChange(ev) {
15
+ value = ev.inputValue;
16
+ onchange && onchange({ value });
17
+ }
8
18
  </script>
9
19
 
10
20
  <div class="wx-radiogroup {type && `wx-${type}`}">
@@ -12,10 +22,10 @@
12
22
  <div class="wx-item">
13
23
  <RadioButton
14
24
  label={option.label}
15
- value={option.value}
16
- checked={value === option.value}
17
- bind:groupValue={value}
25
+ inputValue={option.id}
26
+ value={value === option.id}
18
27
  {name}
28
+ onchange={handleChange}
19
29
  />
20
30
  </div>
21
31
  {/each}
@@ -4,10 +4,12 @@
4
4
  let {
5
5
  value = $bindable(""),
6
6
  options = [],
7
- placeholder = "Click to select",
7
+ placeholder = "",
8
8
  disabled = false,
9
9
  error = false,
10
10
  title = "",
11
+ textField = "label",
12
+ clear = false,
11
13
  children: kids,
12
14
  onchange,
13
15
  } = $props();
@@ -26,13 +28,18 @@
26
28
  function select({ id }) {
27
29
  if (id || id === 0) {
28
30
  value = id;
29
- const obj = options.find(a => a.id === id);
30
31
 
31
32
  navigate(null);
32
- onchange && onchange({ value: obj });
33
+ onchange && onchange({ value });
33
34
  }
34
35
  }
35
36
 
37
+ function unselect(ev) {
38
+ ev.stopPropagation();
39
+ value = "";
40
+ onchange && onchange({ value });
41
+ }
42
+
36
43
  const index = () => options.findIndex(a => a.id === value);
37
44
  </script>
38
45
 
@@ -50,18 +57,22 @@
50
57
  >
51
58
  <div class="wx-label">
52
59
  {#if selected}
53
- {#if kids}{@render kids(selected)}{:else}{selected.name}{/if}
60
+ {#if kids}{@render kids(selected)}{:else}{selected[textField]}{/if}
54
61
  {:else if placeholder}
55
62
  <span class="wx-placeholder">{placeholder}</span>
56
63
  {:else}&nbsp;{/if}
57
64
  </div>
58
65
 
59
- <i class="wx-icon wxi-angle-down"></i>
66
+ {#if clear && !disabled && value}
67
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
68
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
69
+ <i class="wx-icon wxi-close" onclick={unselect}></i>
70
+ {:else}<i class="wx-icon wxi-angle-down"></i>{/if}
60
71
 
61
72
  {#if !disabled}
62
73
  <List items={options} onready={ready} onselect={select}>
63
74
  {#snippet children({ option })}
64
- {#if kids}{@render kids(option)}{:else}{option.name}{/if}
75
+ {#if kids}{@render kids(option)}{:else}{option[textField]}{/if}
65
76
  {/snippet}
66
77
  </List>
67
78
  {/if}
@@ -141,6 +152,13 @@
141
152
  .wx-icon:before {
142
153
  display: block;
143
154
  }
155
+ .wx-icon.wxi-close {
156
+ pointer-events: all;
157
+ }
158
+ .wx-icon.wxi-close:hover {
159
+ background: var(--wx-background-hover);
160
+ border-radius: var(--wx-icon-border-radius);
161
+ }
144
162
 
145
163
  .wx-nowrap .wx-label {
146
164
  white-space: nowrap;
@@ -9,7 +9,7 @@
9
9
 
10
10
  function handleClick(id) {
11
11
  value = id;
12
- onchange && onchange({ id });
12
+ onchange && onchange({ value });
13
13
  }
14
14
  </script>
15
15
 
@@ -17,19 +17,19 @@
17
17
  {#each options as option (option.id)}
18
18
  <button
19
19
  css={option.css}
20
- title={option.title || option.name}
20
+ title={option.title || option.label}
21
21
  class:wx-selected={option.id == value}
22
22
  onclick={() => handleClick(option.id)}
23
23
  >
24
24
  {#if children}{@render children({ option })}{:else}
25
25
  {#if option.icon}
26
26
  <i
27
- class="wx-icon {option.icon} {!option.name
27
+ class="wx-icon {option.icon} {!option.label
28
28
  ? 'wx-only'
29
29
  : ''}"
30
30
  ></i>
31
31
  {/if}
32
- {#if option.name}<span class="wx-label">{option.name}</span
32
+ {#if option.label}<span class="wx-label">{option.label}</span
33
33
  >{/if}
34
34
  {/if}
35
35
  </button>
@@ -2,27 +2,50 @@
2
2
  import { uid } from "wx-lib-dom";
3
3
 
4
4
  let {
5
- label = "label",
6
5
  value = $bindable(""),
7
6
  options = [],
8
7
  placeholder = "",
9
8
  title = "",
10
9
  disabled = false,
11
10
  error = false,
11
+ textField = "label",
12
+ clear = false,
12
13
  id = uid(),
14
+ onchange,
13
15
  } = $props();
16
+
17
+ function unselect() {
18
+ value = "";
19
+ onchange && onchange({ value });
20
+ }
21
+
22
+ function handleChange() {
23
+ onchange && onchange({ value });
24
+ }
14
25
  </script>
15
26
 
16
27
  <div class="wx-select">
17
- <select {id} bind:value {disabled} class:wx-error={error} {title}>
28
+ <select
29
+ {id}
30
+ bind:value
31
+ {disabled}
32
+ class:wx-error={error}
33
+ {title}
34
+ onchange={handleChange}
35
+ >
18
36
  {#each options as option (option.id)}
19
- <option value={option.id}>{option[label]}</option>
37
+ <option value={option.id}>{option[textField]}</option>
20
38
  {/each}
21
39
  </select>
22
40
  {#if !value && value !== 0}
23
41
  <div class="wx-placeholder">{placeholder}</div>
24
42
  {/if}
25
- <i class="wx-icon wxi-angle-down"></i>
43
+
44
+ {#if clear && !disabled && value}
45
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
46
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
47
+ <i class="wx-icon wxi-close" onclick={unselect}></i>
48
+ {:else}<i class="wx-icon wxi-angle-down"></i>{/if}
26
49
  </div>
27
50
 
28
51
  <style>
@@ -123,4 +146,12 @@
123
146
  .wx-icon:before {
124
147
  display: block;
125
148
  }
149
+ .wx-icon.wxi-close {
150
+ pointer-events: all;
151
+ cursor: pointer;
152
+ }
153
+ .wx-icon.wxi-close:hover {
154
+ background: var(--wx-background-hover);
155
+ border-radius: var(--wx-icon-border-radius);
156
+ }
126
157
  </style>
@@ -2,12 +2,12 @@
2
2
  import { clickOutside } from "wx-lib-dom";
3
3
  import { fly } from "svelte/transition";
4
4
 
5
- let { position = "right", children, onclose } = $props();
5
+ let { position = "right", children, oncancel } = $props();
6
6
  </script>
7
7
 
8
8
  <div
9
9
  class="wx-sidearea wx-pos-{position}"
10
- use:clickOutside={() => onclose && onclose()}
10
+ use:clickOutside={() => oncancel && oncancel()}
11
11
  transition:fly={{ x: 650, opacity: 1 }}
12
12
  >
13
13
  {@render children?.()}
@@ -31,9 +31,8 @@
31
31
  }
32
32
  }
33
33
  function onchange({ target }) {
34
- const v = target.value * 1;
35
- change && change({ value: v });
36
- value = v;
34
+ value = target.value * 1;
35
+ change && change({ value });
37
36
  }
38
37
  </script>
39
38
 
@@ -50,7 +49,7 @@
50
49
  {value}
51
50
  {oninput}
52
51
  {onchange}
53
- style={bgStyle}
52
+ style={bgStyle()}
54
53
  />
55
54
  </div>
56
55
  </div>
@@ -15,7 +15,13 @@
15
15
  </script>
16
16
 
17
17
  <label class="wx-switch">
18
- <input type="checkbox" onchange={onChange} {disabled} {id} />
18
+ <input
19
+ type="checkbox"
20
+ checked={value}
21
+ onchange={onChange}
22
+ {disabled}
23
+ {id}
24
+ />
19
25
  <span></span>
20
26
  </label>
21
27
 
@@ -14,13 +14,18 @@
14
14
  error = false,
15
15
  inputStyle = "",
16
16
  title = "",
17
- css = $bindable(""),
17
+ css = "",
18
18
  icon,
19
+ clear = false,
19
20
  onchange: change,
20
21
  } = $props();
21
22
 
22
- if (icon && css.indexOf("wx-icon-left") === -1)
23
- css = "wx-icon-right " + css;
23
+ let cssString = $derived(
24
+ icon && css.indexOf("wx-icon-left") === -1
25
+ ? "wx-icon-right " + css
26
+ : css
27
+ );
28
+ let hasLeftIcon = $derived(icon && css.indexOf("wx-icon-left") !== -1);
24
29
 
25
30
  // svelte-ignore non_reactive_update
26
31
  let input;
@@ -34,9 +39,20 @@
34
39
 
35
40
  const oninput = () => change && change({ value, input: true });
36
41
  const onchange = () => change && change({ value });
42
+
43
+ function clearValue(ev) {
44
+ ev.stopPropagation();
45
+ value = "";
46
+ change && change({ value });
47
+ }
37
48
  </script>
38
49
 
39
- <div class="wx-text {css}" class:wx-error={error} class:wx-disabled={disabled}>
50
+ <div
51
+ class="wx-text {cssString}"
52
+ class:wx-error={error}
53
+ class:wx-disabled={disabled}
54
+ class:wx-clear={clear}
55
+ >
40
56
  {#if type == "password"}
41
57
  <input
42
58
  bind:value
@@ -80,7 +96,12 @@
80
96
  />
81
97
  {/if}
82
98
 
83
- {#if icon}<i class="wx-icon {icon}"></i>{/if}
99
+ {#if clear && !disabled && value}
100
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
101
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
102
+ <i class="wx-icon wxi-close" onclick={clearValue}></i>
103
+ {#if hasLeftIcon}<i class="wx-icon {icon}"></i>{/if}
104
+ {:else if icon}<i class="wx-icon {icon}"></i>{/if}
84
105
  </div>
85
106
 
86
107
  <style>
@@ -114,11 +135,20 @@
114
135
  display: block;
115
136
  }
116
137
 
117
- .wx-icon-left .wx-icon {
138
+ .wx-icon-left .wx-icon:not(.wxi-close) {
118
139
  right: auto;
119
140
  left: var(--wx-input-icon-indent);
120
141
  }
121
142
 
143
+ .wx-icon.wxi-close {
144
+ pointer-events: all;
145
+ cursor: pointer;
146
+ }
147
+ .wx-icon.wxi-close:hover {
148
+ background: var(--wx-background-hover);
149
+ border-radius: var(--wx-icon-border-radius);
150
+ }
151
+
122
152
  input {
123
153
  display: block;
124
154
  width: var(--wx-input-width);
@@ -150,7 +180,8 @@
150
180
  var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2
151
181
  );
152
182
  }
153
- .wx-icon-right input {
183
+ .wx-icon-right input,
184
+ .wx-text.wx-clear input {
154
185
  padding-right: calc(
155
186
  var(--wx-input-icon-size) + var(--wx-input-icon-indent) * 2
156
187
  );
@@ -18,6 +18,7 @@
18
18
  disabled = false,
19
19
  error = false,
20
20
  format = "",
21
+ onchange,
21
22
  } = $props();
22
23
 
23
24
  const { calendar: calendarLocale, formats } =
@@ -51,6 +52,7 @@
51
52
  const next = new Date(safeValue);
52
53
  next.setHours(next.getHours() + (pm ? -12 : 12));
53
54
  value = next;
55
+ onchange && onchange({ value });
54
56
  }
55
57
  function setHours({ value: v }) {
56
58
  if (safeValue.getHours() === v) return;
@@ -58,6 +60,7 @@
58
60
  const next = new Date(safeValue);
59
61
  next.setHours(v);
60
62
  value = next;
63
+ onchange && onchange({ value });
61
64
  }
62
65
  function setMinutes({ value: v }) {
63
66
  if (safeValue.getMinutes() === v) return;
@@ -65,6 +68,7 @@
65
68
  const next = new Date(safeValue);
66
69
  next.setMinutes(v);
67
70
  value = next;
71
+ onchange && onchange({ value });
68
72
  }
69
73
  function formatH(v) {
70
74
  if (h12) {
@@ -95,7 +99,7 @@
95
99
  return (v < 10 && zeroBased ? `0${v}` : `${v}`).slice(-2);
96
100
  }
97
101
 
98
- function cancel() {
102
+ function oncancel() {
99
103
  popup = null;
100
104
  }
101
105
 
@@ -129,7 +133,7 @@
129
133
  />
130
134
 
131
135
  {#if popup && !disabled}
132
- <Dropdown {cancel} width={"unset"}>
136
+ <Dropdown {oncancel} width={"unset"}>
133
137
  <div class="wx-wrapper">
134
138
  <div class="wx-timer">
135
139
  <input
@@ -14,6 +14,7 @@
14
14
  textActive = "",
15
15
  children,
16
16
  active,
17
+ onchange,
17
18
  } = $props();
18
19
 
19
20
  let typeStr = $derived((value ? "pressed" : "") + (type ? " " + type : ""));
@@ -21,7 +22,10 @@
21
22
  function handleClick(ev) {
22
23
  let next = !value;
23
24
  if (onclick) onclick(ev);
24
- if (!ev.defaultPrevented) value = next;
25
+ if (!ev.defaultPrevented) {
26
+ value = next;
27
+ onchange && onchange({ value });
28
+ }
25
29
  }
26
30
  </script>
27
31
 
@@ -35,7 +35,7 @@
35
35
 
36
36
  if (part === "normal") value = new Date(current);
37
37
 
38
- oncancel();
38
+ oncancel && oncancel();
39
39
  }
40
40
  </script>
41
41
 
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { onMount } from "svelte";
2
+ import { onMount, getContext } from "svelte";
3
3
  import { getListHandlers } from "./listnav";
4
4
  import Dropdown from "../Dropdown.svelte";
5
5
 
@@ -8,6 +8,8 @@
8
8
  let list = $state();
9
9
  let navIndex = $state(null);
10
10
 
11
+ const _ = getContext("wx-i18n").getGroup("core");
12
+
11
13
  const { move, keydown, init, navigate } = getListHandlers();
12
14
 
13
15
  const selectItem = ev => {
@@ -24,7 +26,7 @@
24
26
  </script>
25
27
 
26
28
  {#if navIndex !== null}
27
- <Dropdown cancel={() => navigate(null)}>
29
+ <Dropdown oncancel={() => navigate(null)}>
28
30
  <!-- svelte-ignore a11y_click_events_have_key_events -->
29
31
  <!-- svelte-ignore a11y_no_static_element_interactions -->
30
32
  <div
@@ -42,11 +44,11 @@
42
44
  >
43
45
  {#if children}{@render children({
44
46
  option: data,
45
- })}{:else}{data.name}{/if}
47
+ })}{:else}{data.label}{/if}
46
48
  </div>
47
49
  {/each}
48
50
  {:else}
49
- <div class="wx-no-data">No data</div>
51
+ <div class="wx-no-data">{_("No data")}</div>
50
52
  {/if}
51
53
  </div>
52
54
  </Dropdown>
@@ -53,11 +53,12 @@ export function getListHandlers() {
53
53
  const keydown = (ev, position) => {
54
54
  switch (ev.code) {
55
55
  case "Enter":
56
- isVisible ? selectCallback() : setNav(0);
56
+ if (isVisible) selectCallback();
57
+ else setNav(0);
57
58
  break;
58
59
 
59
60
  case "Space":
60
- isVisible ? null : setNav(0);
61
+ if (!isVisible) setNav(0);
61
62
  break;
62
63
 
63
64
  case "Escape":
package/src/index.js CHANGED
@@ -1,6 +1,4 @@
1
- import Area from "./components/Area.svelte";
2
- export { Area, Area as Textarea };
3
-
1
+ export { default as TextArea } from "./components/TextArea.svelte";
4
2
  export { default as Button } from "./components/Button.svelte";
5
3
  export { default as Checkbox } from "./components/Checkbox.svelte";
6
4
  export { default as CheckboxGroup } from "./components/CheckboxGroup.svelte";
@@ -30,7 +28,7 @@ export { default as Field } from "./components/Field.svelte";
30
28
  export { default as Calendar } from "./components/Calendar.svelte";
31
29
  export { default as Month } from "./components/calendar/Month.svelte";
32
30
  export { default as RangeCalendar } from "./components/RangeCalendar.svelte";
33
- export { default as Timepicker } from "./components/Timepicker.svelte";
31
+ export { default as TimePicker } from "./components/TimePicker.svelte";
34
32
  export { default as TwoState } from "./components/TwoState.svelte";
35
33
  export { default as Modal } from "./components/Modal.svelte";
36
34
  export { default as ModalArea } from "./components/ModalArea.svelte";
@@ -48,3 +46,7 @@ export { popupContainer } from "./components/helpers";
48
46
  export { default as SuggestDropdown } from "./components/helpers/SuggestDropdown.svelte";
49
47
 
50
48
  export { en } from "wx-core-locales";
49
+
50
+ import { setEnv } from "wx-lib-dom";
51
+ import { env } from "wx-lib-svelte";
52
+ setEnv(env);
@@ -74,6 +74,7 @@
74
74
  /* icons */
75
75
  --wx-icon-color: var(--wx-color-font-alt);
76
76
  --wx-icon-size: var(--wx-line-height);
77
+ --wx-icon-border-radius: 2px;
77
78
  /* end icons */
78
79
 
79
80
  /* other */
@@ -71,6 +71,7 @@
71
71
  /* icons */
72
72
  --wx-icon-color: #9fa1ae;
73
73
  --wx-icon-size: var(--wx-line-height);
74
+ --wx-icon-border-radius: 2px;
74
75
  /* end icons */
75
76
 
76
77
  /* other */
@@ -71,6 +71,7 @@
71
71
  /* icons */
72
72
  --wx-icon-color: #c0c3ce;
73
73
  --wx-icon-size: var(--wx-line-height);
74
+ --wx-icon-border-radius: 2px;
74
75
  /* end icons */
75
76
 
76
77
  /* other */
package/whatsnew.md CHANGED
@@ -1,3 +1,14 @@
1
+ ### 2.0.0
2
+
3
+ - [add] Svelte 5 support
4
+ - [update] controls with options define them as `id, label`
5
+ - [update] dropdown controls have change event with value instead of selected
6
+ - [update] Area renamed to TextArea
7
+ - [update] Timepicker renamed to TimePicker
8
+ - [update] Sidearea: close event renamed to cancel
9
+ - [update] ColorBoard: change event has extra input parameter
10
+ - [update] Modal boxes: cancel and ok properties renamed to cancel and confirm events
11
+
1
12
  ### 1.3.1
2
13
 
3
14
  - [fix] locale object lacks language marker
File without changes