@intechstudio/grid-uikit 1.20260622.1332 → 1.20260623.833

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.
@@ -39,7 +39,17 @@
39
39
  </script>
40
40
 
41
41
  <label class:checkbox-box={style === "box"} class:disabled>
42
- <button {...$root} use:root class:disabled>
42
+ <button
43
+ {...$root}
44
+ use:root
45
+ class:disabled
46
+ on:keydown={(e) => {
47
+ if (e.key === "Enter") {
48
+ e.preventDefault();
49
+ e.currentTarget.click();
50
+ }
51
+ }}
52
+ >
43
53
  <div class="checkbox-outer" class:disabled>
44
54
  <div
45
55
  style:display={target ? "block" : "none"}
@@ -121,6 +131,10 @@
121
131
  cursor: pointer;
122
132
  font-size: inherit;
123
133
  }
134
+ button:focus {
135
+ outline: var(--focus-outline);
136
+ outline-offset: var(--focus-offset);
137
+ }
124
138
 
125
139
  button.disabled {
126
140
  cursor: default;
@@ -168,13 +168,6 @@
168
168
  }
169
169
  }
170
170
 
171
- function handleFocus() {
172
- if (searchable) {
173
- inputElement.select();
174
- }
175
- open.set(true);
176
- }
177
-
178
171
  function handleBlur() {
179
172
  open.set(false);
180
173
  }
@@ -183,20 +176,27 @@
183
176
  if (e.key === "ArrowDown") {
184
177
  e.preventDefault();
185
178
  if (filteredSuggestions.length === 0) return;
186
- if (!$open) open.set(true);
187
- highlightedIndex =
188
- highlightedIndex < filteredSuggestions.length - 1
189
- ? highlightedIndex + 1
190
- : 0;
191
- scrollIntoView();
179
+ if (!$open) {
180
+ open.set(true);
181
+ } else {
182
+ highlightedIndex =
183
+ highlightedIndex < filteredSuggestions.length - 1
184
+ ? highlightedIndex + 1
185
+ : 0;
186
+ scrollIntoView();
187
+ }
192
188
  } else if (e.key === "ArrowUp") {
193
189
  e.preventDefault();
194
190
  if (filteredSuggestions.length === 0) return;
195
- highlightedIndex =
196
- highlightedIndex > 0
197
- ? highlightedIndex - 1
198
- : filteredSuggestions.length - 1;
199
- scrollIntoView();
191
+ if (!$open) {
192
+ open.set(true);
193
+ } else {
194
+ highlightedIndex =
195
+ highlightedIndex > 0
196
+ ? highlightedIndex - 1
197
+ : filteredSuggestions.length - 1;
198
+ scrollIntoView();
199
+ }
200
200
  } else if (e.key === "Enter") {
201
201
  if (
202
202
  highlightedIndex >= 0 &&
@@ -231,7 +231,7 @@
231
231
  <div class="content">
232
232
  {#if title?.length > 0}
233
233
  <label>
234
- {title}
234
+ <span class="label-text">{title}</span>
235
235
  <div bind:clientWidth={menuWidth}>
236
236
  <input
237
237
  bind:this={inputElement}
@@ -240,7 +240,6 @@
240
240
  use:trigger
241
241
  bind:value={inputValue}
242
242
  on:change={handleChange}
243
- on:focus={handleFocus}
244
243
  on:blur={handleBlur}
245
244
  on:m-keydown={(e) => {
246
245
  e.preventDefault();
@@ -265,7 +264,6 @@
265
264
  use:trigger
266
265
  bind:value={inputValue}
267
266
  on:change={handleChange}
268
- on:focus={handleFocus}
269
267
  on:blur={handleBlur}
270
268
  on:m-keydown={(e) => {
271
269
  e.preventDefault();
@@ -299,11 +297,12 @@
299
297
  {...$close}
300
298
  use:close
301
299
  class="suggestion"
302
- data-highlighted={highlightedIndex === i ? "" : undefined}
303
300
  data-combo-index={i}
304
301
  on:click={() => selected.set(suggestion)}
305
302
  on:mouseenter={() => (highlightedIndex = i)}
306
- >{suggestion.info}</option
303
+ style={highlightedIndex === i
304
+ ? "background-color: var(--popover-selection); color: var(--foreground);"
305
+ : ""}>{suggestion.info}</option
307
306
  >
308
307
  {/each}
309
308
  </div>
@@ -335,18 +334,19 @@
335
334
  color: var(--foreground);
336
335
  font-size: 0.875em;
337
336
  line-height: 1.25em;
337
+ align-items: center;
338
+ }
339
+ .label-text {
338
340
  overflow: hidden;
339
341
  text-overflow: ellipsis;
340
342
  white-space: nowrap;
341
- align-items: center;
343
+ display: block;
342
344
  }
343
345
  input {
344
346
  cursor: auto;
345
- outline: 2px solid transparent;
346
- outline-offset: 2px;
347
+ outline: none;
347
348
  width: 100%;
348
- display: flex;
349
- flex-direction: row;
349
+ box-sizing: border-box;
350
350
  border: 1px solid var(--background-soft);
351
351
  padding: 0.5em;
352
352
  color: var(--foreground);
@@ -354,6 +354,10 @@
354
354
  margin: 0.25em 0em 0em;
355
355
  font-size: inherit;
356
356
  }
357
+ input:focus {
358
+ outline: var(--focus-outline);
359
+ outline-offset: var(--focus-offset);
360
+ }
357
361
  input.error {
358
362
  border-color: var(--error);
359
363
  }
@@ -388,8 +392,7 @@
388
392
  padding-top: 0.25em;
389
393
  padding-bottom: 0.25em;
390
394
  }
391
- option.suggestion:hover,
392
- option.suggestion[data-highlighted] {
395
+ option.suggestion:hover {
393
396
  background-color: var(--popover-selection);
394
397
  color: var(--foreground);
395
398
  }
@@ -397,6 +400,7 @@
397
400
  color: var(--foreground-soft);
398
401
  font-size: 0.875em;
399
402
  line-height: 1.25em;
403
+ margin-top: 0.25em;
400
404
  overflow: hidden;
401
405
  text-overflow: ellipsis;
402
406
  white-space: nowrap;
@@ -84,8 +84,8 @@
84
84
  class:disabled
85
85
  />
86
86
  </div>
87
+ <span class:disabled>{title}</span>
87
88
  </button>
88
- <span class:disabled>{title}</span>
89
89
  {/if}
90
90
  {#if style === "button"}
91
91
  <button
@@ -176,6 +176,12 @@
176
176
  padding: 0; /* 3 */
177
177
  background-color: transparent; /* 2 */
178
178
  cursor: pointer;
179
+ display: inline-flex;
180
+ align-items: center;
181
+ }
182
+ button:focus {
183
+ outline: var(--focus-outline);
184
+ outline-offset: var(--focus-offset);
179
185
  }
180
186
  button.style-button {
181
187
  position: relative;
@@ -183,6 +189,7 @@
183
189
  width: 100%;
184
190
  border-radius: 0.25em;
185
191
  border: 1px solid var(--background-soft);
192
+ justify-content: center;
186
193
  }
187
194
  button.style-button:hover {
188
195
  background-color: var(--background-muted);
@@ -120,6 +120,10 @@
120
120
  background-color: var(--background-muted);
121
121
  cursor: pointer;
122
122
  }
123
+ button.select:focus {
124
+ outline: var(--focus-outline);
125
+ outline-offset: var(--focus-offset);
126
+ }
123
127
  button.disabled {
124
128
  color: var(--foreground-disabled);
125
129
  cursor: default;
@@ -103,6 +103,10 @@
103
103
  border-radius: 9999px;
104
104
  background-color: var(--foreground-muted);
105
105
  }
106
+ span.thumb:focus {
107
+ outline: var(--focus-outline);
108
+ outline-offset: var(--focus-offset);
109
+ }
106
110
 
107
111
  span.container.disabled {
108
112
  pointer-events: none;
@@ -101,8 +101,8 @@
101
101
  font-size: inherit;
102
102
  }
103
103
  input:focus {
104
- outline: 2px solid transparent;
105
- outline-offset: 2px;
104
+ outline: var(--focus-outline);
105
+ outline-offset: var(--focus-offset);
106
106
  }
107
107
  input:disabled {
108
108
  cursor: default;
@@ -143,8 +143,8 @@
143
143
  }
144
144
 
145
145
  button:focus {
146
- outline: 2px solid transparent;
147
- outline-offset: 2px;
146
+ outline: var(--focus-outline);
147
+ outline-offset: var(--focus-offset);
148
148
  }
149
149
 
150
150
  button.grouped {
@@ -185,8 +185,8 @@
185
185
  }
186
186
 
187
187
  .dropdown-button:focus {
188
- outline: 2px solid transparent;
189
- outline-offset: 2px;
188
+ outline: var(--focus-outline);
189
+ outline-offset: var(--focus-offset);
190
190
  }
191
191
 
192
192
  .dropdown-button.grouped {
@@ -20,11 +20,13 @@
20
20
 
21
21
  let showbuttons = $state(false);
22
22
  let showTooltip = $state(false);
23
+ let tooltipKey = $state(0);
23
24
 
24
25
  let tooltipElement: HTMLDivElement | undefined = $state();
25
26
  let previousFocusedElement: HTMLElement | null = null;
26
27
  let closeTimeout: any;
27
28
  let openTimeout: any;
29
+ let isRestoringFocus = false;
28
30
 
29
31
  function handleClick(e: any) {
30
32
  //handleReferenceElementClick(e);
@@ -49,12 +51,11 @@
49
51
  }
50
52
  }
51
53
  if (triggerEvents.includes("show-buttons")) {
52
- if (!showbuttons) {
53
- clearTimeout(openTimeout);
54
- showTooltip = true;
55
- if (buttons.length > 0) {
56
- showbuttons = true;
57
- }
54
+ clearTimeout(openTimeout);
55
+ tooltipKey++;
56
+ showTooltip = true;
57
+ if (buttons.length > 0) {
58
+ showbuttons = true;
58
59
  }
59
60
  }
60
61
  if (triggerEvents.includes("hover") && !showbuttons) {
@@ -85,14 +86,14 @@
85
86
  clearTimeout(openTimeout);
86
87
  closeTimeout = setTimeout(
87
88
  () => {
88
- showTooltip = false;
89
+ close();
89
90
  },
90
91
  instant ? 0 : 100,
91
92
  );
92
93
  }
93
94
  if (triggerEvents.includes("click")) {
94
95
  closeTimeout = setTimeout(() => {
95
- showTooltip = false;
96
+ close();
96
97
  }, 100);
97
98
  }
98
99
  //e.stopPropagation();
@@ -100,16 +101,21 @@
100
101
 
101
102
  function handleReferenceElementFocus(e: any) {
102
103
  if (triggerEvents.includes("focus")) {
104
+ if (isRestoringFocus) return;
103
105
  clearTimeout(closeTimeout);
104
106
  showTooltip = true;
105
107
  }
106
108
  //e.stopPropagation();
107
109
  }
108
110
 
109
- function handleReferenceElementBlur(e: any) {
111
+ function handleReferenceElementBlur(e: FocusEvent) {
110
112
  if (triggerEvents.includes("focus")) {
113
+ const relatedTarget = e.relatedTarget as Node | null;
114
+ if (relatedTarget && tooltipElement?.contains(relatedTarget)) {
115
+ return;
116
+ }
111
117
  closeTimeout = setTimeout(() => {
112
- showTooltip = false;
118
+ close();
113
119
  }, 100);
114
120
  }
115
121
  //e.stopPropagation();
@@ -147,6 +153,17 @@
147
153
  if (tooltipElement) {
148
154
  previousFocusedElement = document.activeElement as HTMLElement | null;
149
155
  tooltipElement.focus();
156
+ const handleFocusOut = (e: FocusEvent) => {
157
+ const relatedTarget = e.relatedTarget as Node | null;
158
+ if (relatedTarget && tooltipElement?.contains(relatedTarget)) {
159
+ return;
160
+ }
161
+ close();
162
+ };
163
+ tooltipElement.addEventListener("focusout", handleFocusOut);
164
+ return () => {
165
+ tooltipElement?.removeEventListener("focusout", handleFocusOut);
166
+ };
150
167
  }
151
168
  });
152
169
 
@@ -204,90 +221,96 @@
204
221
  );
205
222
  }
206
223
 
207
- function close() {
224
+ function close(restoreFocus = true) {
208
225
  clearTimeout(openTimeout);
209
226
  clearTimeout(closeTimeout);
210
227
  showTooltip = false;
211
228
  showbuttons = false;
212
- if (previousFocusedElement) {
229
+ if (restoreFocus && previousFocusedElement) {
230
+ isRestoringFocus = true;
213
231
  previousFocusedElement.focus();
214
232
  previousFocusedElement = null;
233
+ requestAnimationFrame(() => {
234
+ isRestoringFocus = false;
235
+ });
215
236
  }
216
237
  }
217
238
  </script>
218
239
 
219
- <Popover
220
- bind:isOpen={showTooltip}
221
- triggerEvents={["manual"]}
222
- {referenceElement}
223
- bind:placement
224
- spaceAway={10}
225
- >
226
- <!-- svelte-ignore a11y-click-events-have-key-events -->
227
- <!-- svelte-ignore a11y-no-static-element-interactions -->
228
- <div
229
- on:mouseenter={handleMouseEnter}
230
- on:mouseleave={handleMouseLeave}
231
- on:click={handleClick}
232
- bind:this={tooltipElement}
233
- tabindex="-1"
234
- class="{className} tooltip-container"
235
- transition:fade|global={{
236
- duration: instant ? 0 : duration, //Make it instant when explicitly clicked
237
- }}
240
+ {#key tooltipKey}
241
+ <Popover
242
+ isOpen={showTooltip}
243
+ triggerEvents={["manual"]}
244
+ {referenceElement}
245
+ bind:placement
246
+ spaceAway={10}
238
247
  >
248
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
249
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
239
250
  <div
240
- class="tooltip-container-content"
241
- class:tooltip-gap-2={buttons.length > 0}
251
+ on:mouseenter={handleMouseEnter}
252
+ on:mouseleave={handleMouseLeave}
253
+ on:click={handleClick}
254
+ bind:this={tooltipElement}
255
+ tabindex="-1"
256
+ class="{className} tooltip-container"
257
+ transition:fade|global={{
258
+ duration: instant ? 0 : duration, //Make it instant when explicitly clicked
259
+ }}
242
260
  >
243
- {#if typeof component === "undefined"}
244
- <div
245
- class="tooltip-container-text"
246
- class:tooltip-whitespace-nowrap={nowrap}
247
- >
248
- {text}
249
- </div>
250
- {:else}
251
- <svelte:component
252
- this={component.object}
253
- {...component.props}
254
- class="tooltip-container-component"
255
- on:event={interceptEvent}
256
- />
257
- {/if}
258
-
259
- {#if showbuttons}
260
- <div
261
- transition:slide|global={{ duration: instant ? 0 : 100 }}
262
- class="tooltip-container-buttons"
263
- >
264
- {#each buttons as button}
265
- <MoltenPushButton
266
- text={button.label}
267
- snap={"full"}
268
- click={() => {
269
- if (typeof button.handler !== "undefined") {
270
- button.handler();
271
- }
272
- close();
273
- }}
274
- />
275
- {/each}
276
- </div>
277
- {/if}
261
+ <div
262
+ class="tooltip-container-content"
263
+ class:tooltip-gap-2={buttons.length > 0}
264
+ >
265
+ {#if typeof component === "undefined"}
266
+ <div
267
+ class="tooltip-container-text"
268
+ class:tooltip-whitespace-nowrap={nowrap}
269
+ >
270
+ {text}
271
+ </div>
272
+ {:else}
273
+ <svelte:component
274
+ this={component.object}
275
+ {...component.props}
276
+ class="tooltip-container-component"
277
+ on:event={interceptEvent}
278
+ />
279
+ {/if}
280
+
281
+ {#if showbuttons}
282
+ <div
283
+ transition:slide|global={{ duration: instant ? 0 : 100 }}
284
+ class="tooltip-container-buttons"
285
+ >
286
+ {#each buttons as button}
287
+ <MoltenPushButton
288
+ text={button.label}
289
+ snap={"full"}
290
+ click={() => {
291
+ if (typeof button.handler !== "undefined") {
292
+ button.handler();
293
+ }
294
+ close();
295
+ }}
296
+ />
297
+ {/each}
298
+ </div>
299
+ {/if}
300
+ </div>
278
301
  </div>
279
- </div>
280
- <div
281
- transition:fade|global={{
282
- duration: instant ? 0 : duration,
283
- }}
284
- class="tooltip-absolute"
285
- id="arrow"
286
- data-popper-arrow
287
- >
288
- <div class="tooltip-absolute" id="arrow_face" />
289
- </div>
290
- </Popover>
302
+ <div
303
+ transition:fade|global={{
304
+ duration: instant ? 0 : duration,
305
+ }}
306
+ class="tooltip-absolute"
307
+ id="arrow"
308
+ data-popper-arrow
309
+ >
310
+ <div class="tooltip-absolute" id="arrow_face" />
311
+ </div>
312
+ </Popover>
313
+ {/key}
291
314
 
292
315
  <style global>
293
316
  div.tooltip-container {
@@ -299,6 +322,11 @@
299
322
  border-radius: 0.375rem;
300
323
  z-index: 99;
301
324
  padding: 0.25rem;
325
+ outline: 1px dashed transparent;
326
+ }
327
+ div.tooltip-container:focus {
328
+ outline: var(--focus-outline);
329
+ outline-offset: var(--focus-offset);
302
330
  }
303
331
 
304
332
  div.tooltip-container-content {
@@ -26,6 +26,13 @@
26
26
  on:change={handleChange}
27
27
  class="{$$props.class} toggle"
28
28
  {disabled}
29
+ on:keydown={(e) => {
30
+ if (e.key === "Enter") {
31
+ e.preventDefault();
32
+ value = !value;
33
+ handleChange();
34
+ }
35
+ }}
29
36
  />
30
37
  </div>
31
38
 
@@ -49,7 +56,8 @@
49
56
  }
50
57
 
51
58
  input[type="checkbox"]:focus {
52
- outline: 0;
59
+ outline: var(--focus-outline);
60
+ outline-offset: var(--focus-offset);
53
61
  }
54
62
 
55
63
  .toggle {
package/dist/theme.css CHANGED
@@ -26,6 +26,10 @@
26
26
  --accent-muted: color-mix(in srgb, var(--accent), var(--shadow) 30%);
27
27
  --accent-soft: color-mix(in srgb, var(--accent), var(--shadow) 50%);
28
28
 
29
+ --focus: #0000ff;
30
+ --focus-outline: 1px solid var(--focus);
31
+ --focus-offset: 1px;
32
+
29
33
  --error: #dc2626;
30
34
 
31
35
  --popover-background: color-mix(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intechstudio/grid-uikit",
3
- "version": "1.20260622.1332",
3
+ "version": "1.20260623.833",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/intechstudio/grid-uikit.git"
package/src/lib/theme.css CHANGED
@@ -26,6 +26,10 @@
26
26
  --accent-muted: color-mix(in srgb, var(--accent), var(--shadow) 30%);
27
27
  --accent-soft: color-mix(in srgb, var(--accent), var(--shadow) 50%);
28
28
 
29
+ --focus: #0000ff;
30
+ --focus-outline: 1px solid var(--focus);
31
+ --focus-offset: 1px;
32
+
29
33
  --error: #dc2626;
30
34
 
31
35
  --popover-background: color-mix(