@urbicon-ui/blocks 6.24.0 → 6.26.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 (73) hide show
  1. package/README.md +14 -0
  2. package/dist/components/Calendar/CalendarTimeGrid.svelte +2 -1
  3. package/dist/components/Calendar/calendar.variants.d.ts +63 -63
  4. package/dist/components/Calendar/calendar.variants.js +5 -3
  5. package/dist/components/CommandPalette/CommandPalette.svelte +32 -16
  6. package/dist/components/CommandPalette/CommandPalette.svelte.d.ts +1 -1
  7. package/dist/components/CommandPalette/commandPalette.variants.d.ts +10 -0
  8. package/dist/components/CommandPalette/commandPalette.variants.js +9 -7
  9. package/dist/components/CommandPalette/index.d.ts +19 -0
  10. package/dist/components/CompositionBar/CompositionBar.svelte +2 -2
  11. package/dist/components/CompositionBar/composition-bar.variants.js +1 -1
  12. package/dist/components/Planner/planner.variants.js +1 -1
  13. package/dist/components/Sankey/sankey.variants.js +1 -1
  14. package/dist/i18n/index.d.ts +378 -2
  15. package/dist/internal/charts/variants.js +2 -2
  16. package/dist/internal/date-grid/DateGridScaffold.svelte +9 -2
  17. package/dist/internal/date-grid/date-grid.svelte.d.ts +4 -2
  18. package/dist/internal/date-grid/date-grid.svelte.js +63 -7
  19. package/dist/primitives/Alert/alert.variants.d.ts +8 -8
  20. package/dist/primitives/Alert/alert.variants.js +1 -1
  21. package/dist/primitives/Avatar/Avatar.svelte +38 -24
  22. package/dist/primitives/Avatar/index.d.ts +1 -1
  23. package/dist/primitives/Badge/badge.variants.js +1 -1
  24. package/dist/primitives/Button/Button.svelte +12 -25
  25. package/dist/primitives/Button/button.variants.js +2 -2
  26. package/dist/primitives/ButtonGroup/ButtonGroup.svelte +5 -1
  27. package/dist/primitives/Checkbox/checkbox.variants.js +2 -2
  28. package/dist/primitives/Collapsible/Collapsible.svelte +10 -0
  29. package/dist/primitives/Collapsible/index.d.ts +13 -2
  30. package/dist/primitives/ConfirmDialog/ConfirmDialog.svelte +14 -0
  31. package/dist/primitives/ConfirmDialog/index.d.ts +13 -2
  32. package/dist/primitives/Dialog/Dialog.svelte +36 -8
  33. package/dist/primitives/Drawer/Drawer.svelte +34 -7
  34. package/dist/primitives/Input/Input.svelte +7 -1
  35. package/dist/primitives/JourneyTimeline/journey-timeline.variants.d.ts +22 -22
  36. package/dist/primitives/JourneyTimeline/journey-timeline.variants.js +3 -3
  37. package/dist/primitives/Menu/Menu.svelte +8 -0
  38. package/dist/primitives/Menu/index.d.ts +11 -13
  39. package/dist/primitives/Popover/Popover.svelte +107 -4
  40. package/dist/primitives/Popover/index.d.ts +15 -2
  41. package/dist/primitives/Popover/index.js +1 -1
  42. package/dist/primitives/Popover/popover.variants.d.ts +25 -0
  43. package/dist/primitives/Popover/popover.variants.js +35 -0
  44. package/dist/primitives/Progress/progress.variants.js +1 -1
  45. package/dist/primitives/RadioGroup/radioGroup.variants.js +2 -2
  46. package/dist/primitives/Select/index.d.ts +8 -1
  47. package/dist/primitives/Slider/Slider.svelte +32 -3
  48. package/dist/primitives/Spinner/spinner.variants.d.ts +16 -16
  49. package/dist/primitives/Stepper/stepper.variants.d.ts +11 -11
  50. package/dist/primitives/Stepper/stepper.variants.js +2 -2
  51. package/dist/primitives/Textarea/Textarea.svelte +5 -1
  52. package/dist/primitives/Toast/toast.variants.d.ts +12 -12
  53. package/dist/primitives/Tooltip/tooltip.variants.d.ts +3 -3
  54. package/dist/primitives/Tooltip/tooltip.variants.js +14 -3
  55. package/dist/style/foundation.css +41 -7
  56. package/dist/style/interaction.css +19 -2
  57. package/dist/style/semantic.css +84 -1
  58. package/dist/style/themes/forest.css +3 -1
  59. package/dist/style/themes/neutral.css +10 -1
  60. package/dist/style/themes/ocean.css +5 -1
  61. package/dist/style/themes/sunset.css +3 -1
  62. package/dist/utils/compose-handlers.d.ts +72 -0
  63. package/dist/utils/compose-handlers.js +65 -0
  64. package/dist/utils/figma-token-export.js +6 -2
  65. package/dist/utils/guide.svelte.js +92 -29
  66. package/dist/utils/index.d.ts +1 -1
  67. package/dist/utils/index.js +1 -1
  68. package/dist/utils/overlay-tokens.d.ts +17 -0
  69. package/dist/utils/overlay-tokens.js +30 -0
  70. package/dist/utils/overlay.js +24 -2
  71. package/dist/utils/use-floating-panel.svelte.js +9 -3
  72. package/dist/utils/variants.js +5 -1
  73. package/package.json +3 -3
@@ -7,7 +7,7 @@ export * from './id.js';
7
7
  export { observeTargetResolution } from './observe-target.js';
8
8
  export { createOptionalContext } from './optional-context.js';
9
9
  export { overlayStack } from './overlay-stack.svelte.js';
10
- export { type EasingFn, getOverlayMotion, OVERLAY_MOTION_DEFAULTS, type OverlayMotion, type OverlayMotionOverride } from './overlay-tokens.js';
10
+ export { type EasingFn, getOverlayMotion, maxTransitionDurationMs, OVERLAY_MOTION_DEFAULTS, type OverlayMotion, type OverlayMotionOverride } from './overlay-tokens.js';
11
11
  export * from './persistent-state.svelte.js';
12
12
  export { edgeEnabledIndex, nextEnabledIndex } from './roving.js';
13
13
  export { getTierContext, type InteractiveTier, setTierContext, type TierContext } from './tier-context.js';
@@ -7,7 +7,7 @@ export * from './id.js';
7
7
  export { observeTargetResolution } from './observe-target.js';
8
8
  export { createOptionalContext } from './optional-context.js';
9
9
  export { overlayStack } from './overlay-stack.svelte.js';
10
- export { getOverlayMotion, OVERLAY_MOTION_DEFAULTS } from './overlay-tokens.js';
10
+ export { getOverlayMotion, maxTransitionDurationMs, OVERLAY_MOTION_DEFAULTS } from './overlay-tokens.js';
11
11
  export * from './persistent-state.svelte.js';
12
12
  export { edgeEnabledIndex, nextEnabledIndex } from './roving.js';
13
13
  export { getTierContext, setTierContext } from './tier-context.js';
@@ -45,6 +45,23 @@ export interface OverlayMotionOverride {
45
45
  }
46
46
  /** Defaults mirror the CSS custom properties in `interaction.css`. */
47
47
  export declare const OVERLAY_MOTION_DEFAULTS: OverlayMotion;
48
+ /**
49
+ * Longest `transition-duration` currently applying to an element, in ms.
50
+ *
51
+ * Used by Popover's exit-motion lag: the panel's CSS transition (token-driven,
52
+ * per-instance-overridable, collapsed by reduced motion) is the single source
53
+ * of truth for how long closed content must stay mounted, so the lag is read
54
+ * from the live computed style instead of duplicating the token resolution in
55
+ * JS. Returns `0` when the element is missing, has no transition, or the
56
+ * environment has no CSS engine (SSR, jsdom) — callers then tear down
57
+ * synchronously, which keeps unstyled consumers and node tests on the
58
+ * pre-motion behaviour.
59
+ *
60
+ * `transition-duration` computes to a comma list (one entry per transition
61
+ * property); the max governs because the exit isn't over until the slowest
62
+ * property lands.
63
+ */
64
+ export declare function maxTransitionDurationMs(el: Element | null | undefined): number;
48
65
  /**
49
66
  * Read the current overlay motion settings.
50
67
  *
@@ -28,6 +28,36 @@ export const OVERLAY_MOTION_DEFAULTS = {
28
28
  panelScaleStart: 0.96,
29
29
  panelFlyDistance: 320
30
30
  };
31
+ /**
32
+ * Longest `transition-duration` currently applying to an element, in ms.
33
+ *
34
+ * Used by Popover's exit-motion lag: the panel's CSS transition (token-driven,
35
+ * per-instance-overridable, collapsed by reduced motion) is the single source
36
+ * of truth for how long closed content must stay mounted, so the lag is read
37
+ * from the live computed style instead of duplicating the token resolution in
38
+ * JS. Returns `0` when the element is missing, has no transition, or the
39
+ * environment has no CSS engine (SSR, jsdom) — callers then tear down
40
+ * synchronously, which keeps unstyled consumers and node tests on the
41
+ * pre-motion behaviour.
42
+ *
43
+ * `transition-duration` computes to a comma list (one entry per transition
44
+ * property); the max governs because the exit isn't over until the slowest
45
+ * property lands.
46
+ */
47
+ export function maxTransitionDurationMs(el) {
48
+ if (!el || typeof window === 'undefined')
49
+ return 0;
50
+ const raw = getComputedStyle(el).transitionDuration;
51
+ if (!raw)
52
+ return 0;
53
+ let max = 0;
54
+ for (const part of raw.split(',')) {
55
+ const ms = parseDurationMs(part, 0);
56
+ if (ms > max)
57
+ max = ms;
58
+ }
59
+ return max;
60
+ }
31
61
  function parseDurationMs(value, fallback) {
32
62
  if (!value)
33
63
  return fallback;
@@ -18,8 +18,18 @@ export function trapFocus(event, container) {
18
18
  if (!isBrowser)
19
19
  return;
20
20
  const focusable = getFocusableElements(container);
21
- if (focusable.length === 0)
21
+ if (focusable.length === 0) {
22
+ // Nothing tabbable inside the overlay (untitled Dialog with static
23
+ // children, Drawer with hideCloseButton): park focus on the container —
24
+ // the panel that focusFirstElement's fallback focused via tabindex="-1" —
25
+ // instead of letting Tab walk out of the modal. Browsers with a real top
26
+ // layer get this from `showModal()` inertness; the guard keeps the trap's
27
+ // contract honest everywhere else. `contains` includes the container
28
+ // itself, so focus already parked there stays put.
29
+ if (container?.contains(document.activeElement))
30
+ event.preventDefault();
22
31
  return;
32
+ }
23
33
  const first = focusable[0];
24
34
  const last = focusable[focusable.length - 1];
25
35
  if (event.shiftKey) {
@@ -74,8 +84,20 @@ export function focusFirstElement(container) {
74
84
  return;
75
85
  tick().then(() => {
76
86
  const focusable = getFocusableElements(container);
77
- if (focusable.length > 0)
87
+ if (focusable.length > 0) {
78
88
  focusable[0].focus();
89
+ return;
90
+ }
91
+ // No focusable descendant — e.g. an untitled Dialog whose children are
92
+ // static text (no header, so no close button), or a Drawer with
93
+ // hideCloseButton. Fall back to the container itself, which the overlay
94
+ // panels make programmatically focusable via tabindex="-1" (excluded from
95
+ // getFocusableElements, so it never joins the Tab cycle). Without this,
96
+ // focus stays on <body>: the overlay's element-level keydown never fires,
97
+ // leaving ESC to the window fallback and the Tab trap inert until the
98
+ // user clicks in — a WCAG 2.1.2 problem. Mirrors the native <dialog>
99
+ // focusing steps, which likewise fall back to the dialog element.
100
+ container?.focus();
79
101
  });
80
102
  }
81
103
  /**
@@ -80,9 +80,11 @@ export function useFloatingPanel(opts) {
80
80
  if (!isOpen || !ref) {
81
81
  cleanupPosition?.();
82
82
  cleanupPosition = undefined;
83
- // Drop the keyboard-aware height clamp so the next open re-measures from
84
- // the full design cap instead of inheriting a stale value.
85
- floating.style.removeProperty('--blocks-overlay-available-height');
83
+ // The keyboard-aware height clamp is deliberately NOT dropped here: the
84
+ // panel may still be painting its CSS exit transition (allow-discrete /
85
+ // Popover's lagged display), and un-clamping mid-fade would let clamped
86
+ // content grow while it fades out. The show path below resets it before
87
+ // the next open instead.
86
88
  // Guard on the live `:popover-open` state only (not the current mode):
87
89
  // a panel that was promoted to the top layer must still be torn down even
88
90
  // if its mode has since flipped to `fixed`/`inline`.
@@ -102,6 +104,10 @@ export function useFloatingPanel(opts) {
102
104
  }
103
105
  if (zIndexValue)
104
106
  floating.style.zIndex = zIndexValue;
107
+ // Drop the previous open's keyboard-aware height clamp before showing, so
108
+ // this open re-measures from the full design cap instead of inheriting a
109
+ // stale value. (Moved off the hide path — see the comment there.)
110
+ floating.style.removeProperty('--blocks-overlay-available-height');
105
111
  if (useTopLayer && !floating.matches(':popover-open')) {
106
112
  try {
107
113
  floating.showPopover();
@@ -232,7 +232,11 @@ const BUCKET_PATTERNS = [
232
232
  [/^text-shadow-(2xs|xs|sm|md|lg|none)$/, 'text-shadow'],
233
233
  [/^text-shadow$/, 'text-shadow'],
234
234
  [/^text-shadow-/, 'text-shadow-color'],
235
- [/^text-(xs|sm|base|lg|xl|\d+xl)(\/[\w.-]+)?$/, 'text-size'],
235
+ // `\d+xs` covers the library's sub-xs scale (--text-2xs/--text-3xs in
236
+ // foundation.css) and mirrors `\d+xl` for consumer-added steps. Without it
237
+ // `text-2xs` falls through to the text-color catch-all below, so a color
238
+ // override would silently strip the font size.
239
+ [/^text-(\d+xs|xs|sm|base|lg|xl|\d+xl)(\/[\w.-]+)?$/, 'text-size'],
236
240
  // Data-type hints disambiguate the overloaded `text-` arbitraries.
237
241
  [/^text-\[length:/, 'text-size'],
238
242
  [/^text-\[color:/, 'text-color'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urbicon-ui/blocks",
3
- "version": "6.24.0",
3
+ "version": "6.26.0",
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": {
@@ -91,8 +91,8 @@
91
91
  "@sveltejs/package": "^2.5.8",
92
92
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
93
93
  "@tailwindcss/vite": "^4.3.1",
94
- "@urbicon-ui/i18n": "6.24.0",
95
- "@urbicon-ui/shared-types": "6.24.0",
94
+ "@urbicon-ui/i18n": "6.26.0",
95
+ "@urbicon-ui/shared-types": "6.26.0",
96
96
  "prettier": "^3.8.4",
97
97
  "prettier-plugin-svelte": "^4.1.1",
98
98
  "prettier-plugin-tailwindcss": "^0.8.0",