@urbicon-ui/blocks 6.37.0 → 6.37.1

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.
@@ -84,6 +84,10 @@
84
84
  if (normalized !== (value ?? '')) {
85
85
  value = normalized;
86
86
  }
87
+ // Completeness must track the (possibly externally reset) value — a stale
88
+ // `true` after a parent-side clear would swallow the onComplete of the next
89
+ // single-emit fill (paste/autofill), the standard wrong-code retry flow.
90
+ wasComplete = normalized.length === length;
87
91
  });
88
92
 
89
93
  // Stable per-position keys — the index IS the cell identity, but a derived id
@@ -11,10 +11,16 @@ export const qrCodeVariants = tv({
11
11
  variants: {
12
12
  // Optional framing so the code can sit on a guaranteed-light card (the
13
13
  // scan-safe default look) without the consumer hand-building one.
14
+ // `scheme-light` pins `color-scheme: light` on the card, so every
15
+ // `light-dark()` token inside resolves to its light value even in dark
16
+ // mode — without it the card ground flips dark and the `currentColor`
17
+ // modules invert (light-on-dark QR codes fail many scanners). The explicit
18
+ // `text-text-primary` re-derives the module colour under that scheme
19
+ // (inherited `color` is computed on the dark ancestor and would leak in).
14
20
  frame: {
15
21
  none: {},
16
22
  card: {
17
- root: 'bg-surface-base border border-border-subtle rounded-lg p-3 shadow-[var(--blocks-shadow-sm)]'
23
+ root: 'scheme-light bg-surface-base text-text-primary border border-border-subtle rounded-lg p-3 shadow-[var(--blocks-shadow-sm)]'
18
24
  }
19
25
  }
20
26
  },
@@ -66,7 +66,7 @@
66
66
  let hourEl = $state<HTMLInputElement>();
67
67
  let minuteEl = $state<HTMLInputElement>();
68
68
  let secondEl = $state<HTMLInputElement>();
69
- let meridiemEl = $state<HTMLButtonElement>();
69
+ let meridiemEl = $state<HTMLSpanElement>();
70
70
 
71
71
  function pad(n: number): string {
72
72
  return String(n).padStart(2, '0');
@@ -174,7 +174,7 @@
174
174
  minuteEl,
175
175
  withSeconds ? secondEl : undefined,
176
176
  format === '12h' ? meridiemEl : undefined
177
- ].filter(Boolean) as (HTMLInputElement | HTMLButtonElement)[]
177
+ ].filter(Boolean) as (HTMLInputElement | HTMLSpanElement)[]
178
178
  );
179
179
 
180
180
  function advanceFrom(el: HTMLElement) {
@@ -315,6 +315,10 @@
315
315
  switch (e.key) {
316
316
  case 'ArrowUp':
317
317
  case 'ArrowDown':
318
+ // The segment is a spinbutton on a span (html-aria forbids the role on
319
+ // <button>), so Enter/Space activation is wired manually.
320
+ case 'Enter':
321
+ case ' ':
318
322
  e.preventDefault();
319
323
  toggleMeridiem();
320
324
  break;
@@ -331,7 +335,7 @@
331
335
  case 'ArrowLeft':
332
336
  case 'Backspace': {
333
337
  e.preventDefault();
334
- const idx = order.indexOf(e.currentTarget as HTMLButtonElement);
338
+ const idx = order.indexOf(e.currentTarget as HTMLSpanElement);
335
339
  if (idx > 0) order[idx - 1].focus();
336
340
  break;
337
341
  }
@@ -478,11 +482,22 @@
478
482
  />
479
483
  {/if}
480
484
  {#if format === '12h'}
481
- <button
485
+ <!-- A spinbutton (not a button): aria-label on a button would OVERRIDE its
486
+ AM/PM content, so the current state was never announced. As a
487
+ spinbutton the state travels via aria-valuetext — same semantics as
488
+ the sibling segments — and html-aria only permits the role on a
489
+ non-button host, hence the span with manual focus/activation. -->
490
+ <span
482
491
  bind:this={meridiemEl}
483
- type="button"
484
- {disabled}
492
+ role="spinbutton"
493
+ tabindex={disabled ? -1 : 0}
485
494
  aria-label={bt('accessibility.timeMeridiem')}
495
+ aria-valuemin={0}
496
+ aria-valuemax={1}
497
+ aria-valuenow={meridiem === 'AM' ? 0 : 1}
498
+ aria-valuetext={meridiem}
499
+ aria-disabled={disabled ? 'true' : undefined}
500
+ aria-readonly={readonly ? 'true' : undefined}
486
501
  class={unstyled
487
502
  ? (slotClasses?.meridiem ?? '')
488
503
  : styles.meridiem({ class: slotClasses?.meridiem })}
@@ -490,7 +505,7 @@
490
505
  onkeydown={handleMeridiemKeydown}
491
506
  >
492
507
  {meridiem}
493
- </button>
508
+ </span>
494
509
  {/if}
495
510
  </div>
496
511
 
@@ -25,7 +25,8 @@ export const timeInputVariants = tv({
25
25
  meridiem: [
26
26
  'ml-1 font-medium text-text-secondary rounded-sm cursor-pointer select-none',
27
27
  'hover:bg-surface-hover focus-visible:outline-none focus-visible:bg-primary-subtle',
28
- 'disabled:cursor-not-allowed disabled:opacity-50'
28
+ // The segment is a span-hosted spinbutton — no native :disabled state.
29
+ 'aria-disabled:cursor-not-allowed aria-disabled:opacity-50'
29
30
  ],
30
31
  message: ['text-xs']
31
32
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urbicon-ui/blocks",
3
- "version": "6.37.0",
3
+ "version": "6.37.1",
4
4
  "description": "Svelte 5 UI component library with Tailwind CSS 4, OKLCH design tokens and zero runtime dependencies",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,8 +93,8 @@
93
93
  "@sveltejs/package": "^2.5.8",
94
94
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
95
95
  "@tailwindcss/vite": "^4.3.1",
96
- "@urbicon-ui/i18n": "6.37.0",
97
- "@urbicon-ui/shared-types": "6.37.0",
96
+ "@urbicon-ui/i18n": "6.37.1",
97
+ "@urbicon-ui/shared-types": "6.37.1",
98
98
  "prettier": "^3.8.4",
99
99
  "prettier-plugin-svelte": "^4.1.1",
100
100
  "prettier-plugin-tailwindcss": "^0.8.0",