@sveltia/ui 0.1.0 → 0.1.2

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.
@@ -47,7 +47,7 @@
47
47
  let inputComponent;
48
48
  /** @type {(Popup| undefined)} */
49
49
  let popupComponent;
50
- let open = writable(false);
50
+ let isPopupOpen = writable(false);
51
51
 
52
52
  $: {
53
53
  dispatch('change', { target: inputComponent?.element, value });
@@ -92,12 +92,12 @@
92
92
  {disabled}
93
93
  class="ternary iconic"
94
94
  iconName="expand_more"
95
- iconLabel={$open ? $_('sui._.collapse') : $_('sui._.expand')}
95
+ iconLabel={$isPopupOpen ? $_('sui._.collapse') : $_('sui._.expand')}
96
96
  on:click={(event) => {
97
97
  event.stopPropagation();
98
98
 
99
99
  if (!disabled) {
100
- open.set(!$open);
100
+ $isPopupOpen = !$isPopupOpen;
101
101
  }
102
102
  }}
103
103
  />
@@ -105,7 +105,7 @@
105
105
  <Popup
106
106
  anchor={comboboxElement || inputComponent?.element}
107
107
  {position}
108
- bind:open
108
+ bind:open={isPopupOpen}
109
109
  bind:this={popupComponent}
110
110
  >
111
111
  <Listbox
@@ -43,16 +43,16 @@
43
43
  align-items: center;
44
44
  border-color: var(--control-border-color);
45
45
  }
46
- .tab-list:global([aria-orientation="horizontal"]) {
46
+ .tab-list[aria-orientation=horizontal] {
47
47
  gap: 16px;
48
48
  margin: 0 0 32px;
49
49
  border-width: 0 0 1px;
50
50
  padding: 0 16px;
51
51
  }
52
- .tab-list:global([aria-orientation="horizontal"]) :global(button) {
52
+ .tab-list[aria-orientation=horizontal] :global(button) {
53
53
  border-width: 0 0 2px 0;
54
54
  }
55
- .tab-list:global([aria-orientation="vertical"]) {
55
+ .tab-list[aria-orientation=vertical] {
56
56
  gap: 8px;
57
57
  flex-direction: column;
58
58
  margin: 0 32px 0 0;
@@ -60,7 +60,7 @@
60
60
  padding: 8px 0;
61
61
  width: 240px;
62
62
  }
63
- .tab-list:global([aria-orientation="vertical"]) :global(button) {
63
+ .tab-list[aria-orientation=vertical] :global(button) {
64
64
  border-width: 0 2px 0 0;
65
65
  width: 100%;
66
66
  }
@@ -137,10 +137,10 @@ button > :global(*) {
137
137
  button:global(:not(:disabled):focus-visible) {
138
138
  z-index: 1;
139
139
  }
140
- button:global([hidden]) {
140
+ button[hidden] {
141
141
  display: none !important;
142
142
  }
143
- button:global([disabled]) {
143
+ button[disabled] {
144
144
  opacity: 0.4;
145
145
  cursor: default;
146
146
  pointer-events: none;
@@ -172,14 +172,14 @@ button:global(.secondary) {
172
172
  color: var(--highlight-foreground-color);
173
173
  background-color: var(--ternary-background-color);
174
174
  }
175
- button:global(.secondary):global([aria-pressed="true"]) {
175
+ button:global(.secondary)[aria-pressed=true] {
176
176
  background-color: var(--primary-accent-color);
177
177
  }
178
178
  button:global(.ternary) {
179
179
  color: var(--primary-foreground-color);
180
180
  padding: 0 8px;
181
181
  }
182
- button:global(.ternary):global([aria-pressed="true"]) {
182
+ button:global(.ternary)[aria-pressed=true] {
183
183
  background-color: var(--highlight-background-color);
184
184
  }
185
185
  button:global(.danger) {
@@ -48,13 +48,15 @@
48
48
  const dispatch = createEventDispatcher();
49
49
  /** @type {?HTMLDialogElement} */
50
50
  let dialog;
51
+ let showDialog = false;
51
52
  let showContent = false;
52
- let showContentTimer = 0;
53
+ let closeDialogTimer = 0;
53
54
 
54
55
  $: {
55
56
  if (dialog) {
56
57
  if (open) {
57
- window.clearTimeout(showContentTimer);
58
+ window.clearTimeout(closeDialogTimer);
59
+ (document.querySelector('.sui.app-shell') || document.body).appendChild(dialog);
58
60
  showContent = true;
59
61
 
60
62
  if (modal) {
@@ -62,11 +64,17 @@
62
64
  } else {
63
65
  dialog.show();
64
66
  }
67
+
68
+ window.requestAnimationFrame(() => {
69
+ showDialog = true;
70
+ });
65
71
  } else {
66
- dialog.close();
72
+ showDialog = false;
67
73
 
68
- showContentTimer = window.setTimeout(() => {
74
+ closeDialogTimer = window.setTimeout(() => {
69
75
  showContent = false;
76
+ dialog?.close();
77
+ dialog?.remove();
70
78
  }, 500);
71
79
 
72
80
  if (dialog.returnValue === 'ok') {
@@ -83,8 +91,13 @@
83
91
  }
84
92
 
85
93
  onMount(() => {
86
- // Avoid nested dialogs
87
- (document.querySelector('.sui.app-shell') || document.body).appendChild(dialog);
94
+ dialog.remove();
95
+
96
+ // onUnmount
97
+ return () => {
98
+ dialog?.close();
99
+ dialog?.remove();
100
+ };
88
101
  });
89
102
  </script>
90
103
 
@@ -92,6 +105,7 @@
92
105
  <dialog
93
106
  bind:this={dialog}
94
107
  class="sui dialog {className} {size}"
108
+ class:open={showDialog}
95
109
  on:click={({ target }) => {
96
110
  if (closeOnBackdropClick && target?.matches('dialog')) {
97
111
  dialog.returnValue = 'cancel';
@@ -177,25 +191,24 @@
177
191
  justify-content: center;
178
192
  align-items: center;
179
193
  background-color: var(--popup-backdrop-color);
180
- backdrop-filter: blur(8px);
181
- transition: all 200ms;
182
194
  }
183
- dialog:not([open]) {
184
- opacity: 0;
195
+ dialog.open form {
196
+ opacity: 1;
197
+ transform: scale(100%);
198
+ transition-duration: 100ms;
199
+ }
200
+ dialog:not(.open) {
185
201
  pointer-events: none !important;
186
202
  }
187
- dialog:not([open]) form {
203
+ dialog:not(.open) form {
204
+ opacity: 0;
188
205
  transform: scale(90%);
206
+ pointer-events: none;
207
+ transition-duration: 200ms;
189
208
  }
190
- dialog:not([open]) :global(*) {
209
+ dialog:not(.open) :global(*) {
191
210
  pointer-events: none !important;
192
211
  }
193
- dialog[open] {
194
- opacity: 1;
195
- }
196
- dialog[open] form {
197
- transform: scale(100%);
198
- }
199
212
  dialog :global(a),
200
213
  dialog :global(input),
201
214
  dialog :global(textarea),
@@ -207,9 +220,11 @@ dialog form {
207
220
  display: flex;
208
221
  flex-direction: column;
209
222
  border-radius: 4px;
210
- background-color: var(--secondary-background-color);
223
+ background-color: var(--secondary-background-color-translucent);
224
+ backdrop-filter: blur(16px);
211
225
  box-shadow: 0 8px 16px var(--popup-shadow-color);
212
- transition: all 200ms;
226
+ will-change: opacity, transform;
227
+ transition-property: opacity, transform;
213
228
  }
214
229
  dialog.small form {
215
230
  width: 400px;
@@ -41,10 +41,10 @@
41
41
  bind:this={buttonComponent}
42
42
  on:click
43
43
  on:mouseenter={() => {
44
- isPopupOpen.set(true);
44
+ $isPopupOpen = true;
45
45
  }}
46
46
  on:mouseleave={() => {
47
- isPopupOpen.set(false);
47
+ $isPopupOpen = false;
48
48
  }}
49
49
  >
50
50
  {#if iconName}
@@ -18,6 +18,7 @@
18
18
  /** @type {(String|undefined)} */
19
19
  export let value = undefined;
20
20
 
21
+ export let disabled = false;
21
22
  export let min = undefined;
22
23
  export let max = undefined;
23
24
  export let step = 1;
@@ -45,6 +46,7 @@
45
46
  <TextInput
46
47
  bind:this={component}
47
48
  bind:value
49
+ {disabled}
48
50
  role="spinbutton"
49
51
  aria-valuenow={Number(value || 0)}
50
52
  aria-invalid={Number.isNaN(Number(value))}
@@ -67,7 +69,7 @@
67
69
  />
68
70
  <Button
69
71
  class="iconic"
70
- disabled={Number.isNaN(Number(value))}
72
+ disabled={disabled || Number.isNaN(Number(value))}
71
73
  iconLabel={$_('sui.number_input.decrease')}
72
74
  iconName={'arrow_downward'}
73
75
  on:click={() => {
@@ -76,7 +78,7 @@
76
78
  />
77
79
  <Button
78
80
  class="iconic"
79
- disabled={Number.isNaN(Number(value))}
81
+ disabled={disabled || Number.isNaN(Number(value))}
80
82
  iconLabel={$_('sui.number_input.increase')}
81
83
  iconName={'arrow_upward'}
82
84
  on:click={() => {
@@ -5,6 +5,7 @@
5
5
  export default class NumberInput extends SvelteComponentTyped<{
6
6
  [x: string]: any;
7
7
  class?: string;
8
+ disabled?: boolean;
8
9
  value?: string;
9
10
  min?: any;
10
11
  max?: any;
@@ -24,6 +25,7 @@ declare const __propDef: {
24
25
  props: {
25
26
  [x: string]: any;
26
27
  class?: string;
28
+ disabled?: boolean;
27
29
  value?: (string | undefined);
28
30
  min?: any;
29
31
  max?: any;
@@ -53,6 +53,7 @@
53
53
  --content-background-color: hsl(var(--background-color-1-hsl));
54
54
  --primary-background-color: hsl(var(--background-color-2-hsl));
55
55
  --secondary-background-color: hsl(var(--background-color-3-hsl));
56
+ --secondary-background-color-translucent: hsl(var(--background-color-3-hsl) / 88%);
56
57
  --ternary-background-color: hsl(var(--background-color-4-hsl));
57
58
  --control-background-color: hsl(var(--background-color-1-hsl));
58
59
  --disabled-background-color: hsl(var(--background-color-4-hsl));
@@ -60,8 +61,8 @@
60
61
  --primary-border-color: hsl(var(--border-color-1-hsl));
61
62
  --secondary-border-color: hsl(var(--border-color-2-hsl));
62
63
  --control-border-color: hsl(var(--border-color-2-hsl));
63
- --popup-shadow-color: hsl(var(--shadow-color) / 20%);
64
- --popup-backdrop-color: hsl(var(--shadow-color) / 10%);
64
+ --popup-shadow-color: hsl(var(--shadow-color) / 40%);
65
+ --popup-backdrop-color: hsl(var(--shadow-color) / 40%);
65
66
  --default-font-family: "Merriweather Sans", sans-serif;
66
67
  --default-font-size: 13px;
67
68
  --default-font-weight-regular: 300;
@@ -278,5 +279,6 @@
278
279
  -webkit-user-select: none;
279
280
  user-select: none;
280
281
  touch-action: none;
282
+ overflow-anchor: none;
281
283
  cursor: default;
282
284
  }</style>
@@ -26,8 +26,9 @@
26
26
 
27
27
  export let open = writable(false);
28
28
 
29
+ let showDialog = false;
29
30
  let showContent = false;
30
- let showContentTimer = 0;
31
+ let closeDialogTimer = 0;
31
32
 
32
33
  let style = writable({
33
34
  inset: undefined,
@@ -45,27 +46,38 @@
45
46
  $: {
46
47
  if (dialog) {
47
48
  if ($open) {
48
- window.clearTimeout(showContentTimer);
49
+ window.clearTimeout(closeDialogTimer);
50
+ (document.querySelector('.sui.app-shell') || document.body).appendChild(dialog);
49
51
  showContent = true;
50
-
51
52
  dialog.showModal();
53
+
54
+ window.requestAnimationFrame(() => {
55
+ showDialog = true;
56
+ });
52
57
  } else {
53
- showContentTimer = window.setTimeout(() => {
58
+ showDialog = false;
59
+
60
+ closeDialogTimer = window.setTimeout(() => {
54
61
  showContent = false;
62
+ dialog?.close();
63
+ dialog?.remove();
55
64
  }, 500);
56
-
57
- dialog.close();
58
65
  }
59
66
  }
60
67
  }
61
68
 
62
69
  onMount(() => {
63
- // Avoid nested dialogs
64
- (document.querySelector('.sui.app-shell') || document.body).appendChild(dialog);
70
+ dialog.remove();
71
+
72
+ // onUnmount
73
+ return () => {
74
+ dialog?.close();
75
+ dialog?.remove();
76
+ };
65
77
  });
66
78
  </script>
67
79
 
68
- <dialog class="sui popup" bind:this={dialog} class:open={$open}>
80
+ <dialog class="sui popup" bind:this={dialog} class:open={showDialog}>
69
81
  <!-- Prevent the first item in the slot, e.g. a menu item, from being focused by adding `tabindex`
70
82
  to the container -->
71
83
  <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
@@ -83,8 +95,10 @@
83
95
  </div>
84
96
  </dialog>
85
97
 
86
- <style>.popup .content {
87
- outline-width: 0 !important;
98
+ <style>.popup.open .content {
99
+ opacity: 1;
100
+ transform: translateY(2px);
101
+ transition-duration: 100ms;
88
102
  }
89
103
  .popup:not(.open) {
90
104
  pointer-events: none;
@@ -93,18 +107,17 @@
93
107
  opacity: 0;
94
108
  transform: translateY(-8px);
95
109
  pointer-events: none;
110
+ transition-duration: 200ms;
96
111
  }
97
112
 
98
113
  .content {
99
114
  position: fixed;
100
115
  overflow-y: auto;
116
+ outline-width: 0 !important;
101
117
  color: var(--primary-foreground-color);
102
- background-color: var(--secondary-background-color);
118
+ background-color: var(--secondary-background-color-translucent);
103
119
  backdrop-filter: blur(16px);
104
120
  box-shadow: 0 8px 16px var(--popup-shadow-color);
105
121
  will-change: opacity, transform;
106
- transform: translateY(2px);
107
122
  transition-property: opacity, transform;
108
- transition-duration: 200ms;
109
- transition-delay: 100ms;
110
123
  }</style>
@@ -13,6 +13,7 @@
13
13
  --content-background-color: hsl(var(--background-color-1-hsl));
14
14
  --primary-background-color: hsl(var(--background-color-2-hsl));
15
15
  --secondary-background-color: hsl(var(--background-color-3-hsl));
16
+ --secondary-background-color-translucent: hsl(var(--background-color-3-hsl) / 88%);
16
17
  --ternary-background-color: hsl(var(--background-color-4-hsl));
17
18
  --control-background-color: hsl(var(--background-color-1-hsl));
18
19
  --disabled-background-color: hsl(var(--background-color-4-hsl));
@@ -22,8 +23,8 @@
22
23
  --secondary-border-color: hsl(var(--border-color-2-hsl));
23
24
  --control-border-color: hsl(var(--border-color-2-hsl));
24
25
  // Shadows
25
- --popup-shadow-color: hsl(var(--shadow-color) / 20%);
26
- --popup-backdrop-color: hsl(var(--shadow-color) / 10%);
26
+ --popup-shadow-color: hsl(var(--shadow-color) / 40%);
27
+ --popup-backdrop-color: hsl(var(--shadow-color) / 40%);
27
28
  // Fonts
28
29
  --default-font-family: "Merriweather Sans", sans-serif;
29
30
  --default-font-size: 13px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -8,6 +8,7 @@
8
8
  "build": "svelte-kit sync && svelte-package -o package",
9
9
  "build:watch": "svelte-kit sync && svelte-package -o package --watch",
10
10
  "preview": "vite preview",
11
+ "publish": "vite build && npm publish --access public",
11
12
  "check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
12
13
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
13
14
  "format": "prettier --plugin-search-dir . --write .",
@@ -23,16 +24,16 @@
23
24
  "svelte": "^3.55.1"
24
25
  },
25
26
  "devDependencies": {
26
- "@babel/core": "^7.21.0",
27
- "@babel/eslint-parser": "^7.19.1",
27
+ "@babel/core": "^7.21.3",
28
+ "@babel/eslint-parser": "^7.21.3",
28
29
  "@playwright/test": "^1.31.2",
29
30
  "@sveltejs/adapter-auto": "2.0.0",
30
- "@sveltejs/kit": "1.9.3",
31
- "@sveltejs/package": "^2.0.0",
32
- "cspell": "^6.27.0",
33
- "eslint": "^8.35.0",
31
+ "@sveltejs/kit": "1.11.0",
32
+ "@sveltejs/package": "^2.0.2",
33
+ "cspell": "^6.29.3",
34
+ "eslint": "^8.36.0",
34
35
  "eslint-config-airbnb-base": "^15.0.0",
35
- "eslint-config-prettier": "^8.6.0",
36
+ "eslint-config-prettier": "^8.7.0",
36
37
  "eslint-plugin-import": "^2.27.5",
37
38
  "eslint-plugin-svelte3": "^4.0.0",
38
39
  "npm-run-all": "^4.1.5",
@@ -40,17 +41,17 @@
40
41
  "postcss-html": "^1.5.0",
41
42
  "prettier": "^2.8.4",
42
43
  "prettier-plugin-svelte": "^2.9.0",
43
- "sass": "^1.58.3",
44
+ "sass": "^1.59.3",
44
45
  "stylelint": "^15.2.0",
45
46
  "stylelint-config-recommended-scss": "^9.0.1",
46
- "stylelint-scss": "^4.4.0",
47
- "svelte-check": "^3.0.4",
47
+ "stylelint-scss": "^4.5.0",
48
+ "svelte-check": "^3.1.4",
48
49
  "svelte-i18n": "^3.6.0",
49
50
  "svelte-migrate": "^1.1.3",
50
- "svelte-preprocess": "^5.0.1",
51
+ "svelte-preprocess": "^5.0.2",
51
52
  "tslib": "^2.5.0",
52
- "vite": "^4.1.4",
53
- "vitest": "^0.29.2"
53
+ "vite": "^4.2.0",
54
+ "vitest": "^0.29.3"
54
55
  },
55
56
  "exports": {
56
57
  "./package.json": "./package.json",