@urbicon-ui/blocks 6.3.15 → 6.4.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.
@@ -32,7 +32,7 @@
32
32
 
33
33
  const guide = getGuideContext();
34
34
 
35
- if (import.meta.env.DEV && !guide) {
35
+ if (import.meta.env?.DEV && !guide) {
36
36
  console.warn(
37
37
  '[Guide] <Guide> is used without a <GuideProvider> ancestor — the tour will not render.'
38
38
  );
@@ -217,7 +217,7 @@
217
217
  // clickable, and only an app-side controller.next() from outside the spotlight can advance.
218
218
  // Usually a step-definition mistake; mirrors the unresolved-target warning.
219
219
  $effect(() => {
220
- if (!import.meta.env.DEV || !guide) return;
220
+ if (!import.meta.env?.DEV || !guide) return;
221
221
  if (step?.advance === 'action' && !step.interactive) {
222
222
  console.warn(
223
223
  `[Guide] tour "${guide.activeTour?.id}" step ${stepIndex}: advance:'action' without ` +
@@ -22,7 +22,7 @@
22
22
 
23
23
  const guide = getGuideContext();
24
24
 
25
- if (import.meta.env.DEV && !guide) {
25
+ if (import.meta.env?.DEV && !guide) {
26
26
  console.warn(
27
27
  '[Guide] <GuideBeacon> is used without a <GuideProvider> ancestor — it will not render.'
28
28
  );
@@ -37,7 +37,7 @@
37
37
 
38
38
  const guide = getGuideContext();
39
39
 
40
- if (import.meta.env.DEV && !guide) {
40
+ if (import.meta.env?.DEV && !guide) {
41
41
  console.warn(
42
42
  '[Guide] <GuideHint> is used without a <GuideProvider> ancestor — it will not render.'
43
43
  );
@@ -75,7 +75,7 @@
75
75
  $effect(() => {
76
76
  if (trigger === 'manual') {
77
77
  if (open) dismissed = false;
78
- } else if (import.meta.env.DEV && open) {
78
+ } else if (import.meta.env?.DEV && open) {
79
79
  console.warn('[Guide] <GuideHint open> is ignored unless trigger="manual".');
80
80
  }
81
81
  });
@@ -179,7 +179,7 @@
179
179
  // DEV resilience: a requested hint whose target can't be resolved is a silent
180
180
  // no-op otherwise — warn so a wrong `for` id is noticed (mirrors the engine).
181
181
  $effect(() => {
182
- if (import.meta.env.DEV && guide && visible && !guide.resolveTarget(topicId)) {
182
+ if (import.meta.env?.DEV && guide && visible && !guide.resolveTarget(topicId)) {
183
183
  console.warn(
184
184
  `[Guide] <GuideHint for="${topicId}"> cannot anchor — no element with [data-guide="${topicId}"] (or registered target) found.`
185
185
  );
@@ -24,7 +24,7 @@
24
24
 
25
25
  const guide = getGuideContext();
26
26
 
27
- if (import.meta.env.DEV && !guide) {
27
+ if (import.meta.env?.DEV && !guide) {
28
28
  console.warn(
29
29
  '[Guide] <GuideMarker> is used without a <GuideProvider> ancestor — it renders inert.'
30
30
  );
@@ -18,7 +18,7 @@
18
18
 
19
19
  const guide = getGuideContext();
20
20
 
21
- if (import.meta.env.DEV && !guide) {
21
+ if (import.meta.env?.DEV && !guide) {
22
22
  console.warn(
23
23
  '[Guide] <GuideMention> is used without a <GuideProvider> ancestor — it renders as plain text.'
24
24
  );
@@ -42,7 +42,7 @@
42
42
  const interactive = $derived(!!guide && effectiveDirection !== 'to-guide');
43
43
 
44
44
  $effect(() => {
45
- if (import.meta.env.DEV && guide && effectiveDirection === 'to-guide') {
45
+ if (import.meta.env?.DEV && guide && effectiveDirection === 'to-guide') {
46
46
  console.warn(
47
47
  `[Guide] <GuideMention for="${topicId}"> points at a topic whose direction excludes Guide→UI ('to-guide') — it renders as plain text.`
48
48
  );
@@ -35,7 +35,7 @@
35
35
  // Re-registers if the id changes; releases it on unmount.
36
36
  $effect(() => guide?.registerPanel(panelId));
37
37
 
38
- if (import.meta.env.DEV && !guide) {
38
+ if (import.meta.env?.DEV && !guide) {
39
39
  console.warn(
40
40
  '[Guide] <GuidePanel> is used without a <GuideProvider> ancestor — it will not render.'
41
41
  );
@@ -88,7 +88,7 @@
88
88
  // shows an empty body with no signal. Deferred past the current flush via `tick()` so a
89
89
  // sibling <GuideArticle> registering in the same render isn't a false positive.
90
90
  $effect(() => {
91
- if (!import.meta.env.DEV) return;
91
+ if (!import.meta.env?.DEV) return;
92
92
  const id = activeArticle;
93
93
  if (!id) return;
94
94
  let cancelled = false;
@@ -18,7 +18,10 @@ export const badgeVariants = tv({
18
18
  'transition-[color,background-color,border-color,box-shadow,opacity] duration-[var(--blocks-duration-fast)] ease-out'
19
19
  // Radius driven by `tier` axis below.
20
20
  ],
21
- content: ['flex items-center gap-inherit'],
21
+ // `[gap:inherit]` (arbitrary property), NOT `gap-inherit` — Tailwind v4 emits
22
+ // no `gap-inherit` rule, so the icon↔label gap would collapse to 0. The
23
+ // arbitrary property inherits `base`'s per-size gap. (Codeberg #21)
24
+ content: ['flex items-center [gap:inherit]'],
22
25
  // tier: modify — small remove-control on a commit-tier badge.
23
26
  removeButton: [
24
27
  'ml-1 shrink-0 rounded-modify transition-colors text-current',
@@ -10,7 +10,13 @@ export const buttonVariants = tv({
10
10
  'disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none'
11
11
  ],
12
12
  content: [
13
- 'flex items-center gap-inherit transition-opacity duration-[var(--blocks-duration-fast)]'
13
+ // `[gap:inherit]` (arbitrary property), NOT `gap-inherit`: Tailwind v4 has
14
+ // no `gap-inherit` utility — the spacing-based `gap-*` scale has no
15
+ // `inherit` member (unlike `text-inherit`/`border-inherit`), so that class
16
+ // emits no rule and the icon↔label gap silently collapses to 0. The
17
+ // arbitrary property makes `content` inherit `base`'s per-size gap as
18
+ // intended. (Codeberg #21)
19
+ 'flex items-center [gap:inherit] transition-opacity duration-[var(--blocks-duration-fast)]'
14
20
  ],
15
21
  spinner: [
16
22
  'flex items-center justify-center opacity-0 pointer-events-none transition-opacity duration-[var(--blocks-duration-fast)]'
@@ -104,6 +104,25 @@
104
104
  // Focus never leaves the `<input>` while open — the active option is
105
105
  // surfaced via `aria-activedescendant`, not by moving DOM focus into
106
106
  // the listbox.
107
+ //
108
+ // The focus restore in `select`/`clear` must NOT re-open the listbox the way
109
+ // a user-initiated focus does. `inputEl.focus()` dispatches `focus`
110
+ // synchronously, so without this guard `handleFocus` would flip `open = true`
111
+ // again on the very next line — negating the `open = false` above and leaving
112
+ // the listbox open after every mouse-click selection/clear (Codeberg #19).
113
+ // The flag is raised immediately before `focus()` and lowered immediately
114
+ // after, so it masks only that one synchronous event; when `focus()` is a
115
+ // no-op (input already focused, e.g. an Enter-key selection) it fires no
116
+ // `focus` event and the flag is simply lowered again — never left dangling
117
+ // for the next genuine focus.
118
+ let suppressFocusOpen = false;
119
+
120
+ function focusInputWithoutOpening() {
121
+ suppressFocusOpen = true;
122
+ inputEl?.focus();
123
+ suppressFocusOpen = false;
124
+ }
125
+
107
126
  function select(opt: ComboboxOption<T>) {
108
127
  if (opt.disabled) return;
109
128
  value = opt.value;
@@ -111,7 +130,7 @@
111
130
  open = false;
112
131
  activeIndex = -1;
113
132
  onValueChange?.(opt.value);
114
- inputEl?.focus();
133
+ focusInputWithoutOpening();
115
134
  }
116
135
 
117
136
  function clear() {
@@ -120,7 +139,7 @@
120
139
  open = false;
121
140
  activeIndex = -1;
122
141
  onValueChange?.(null);
123
- inputEl?.focus();
142
+ focusInputWithoutOpening();
124
143
  }
125
144
 
126
145
  function handleInput() {
@@ -133,6 +152,7 @@
133
152
  }
134
153
 
135
154
  function handleFocus() {
155
+ if (suppressFocusOpen) return;
136
156
  if (!disabled) open = true;
137
157
  }
138
158
 
@@ -42,7 +42,7 @@
42
42
  }: DialogProps = $props();
43
43
 
44
44
  if (
45
- import.meta.env.DEV &&
45
+ import.meta.env?.DEV &&
46
46
  hideCloseButton &&
47
47
  closeOnEscape === false &&
48
48
  closeOnBackdropClick === false
@@ -42,7 +42,7 @@
42
42
  }: DrawerProps = $props();
43
43
 
44
44
  if (
45
- import.meta.env.DEV &&
45
+ import.meta.env?.DEV &&
46
46
  hideCloseButton &&
47
47
  closeOnEscape === false &&
48
48
  closeOnBackdropClick === false
@@ -109,7 +109,7 @@ export interface GuideControllerOptions {
109
109
  storage?: GuideStorageAdapter;
110
110
  /** Overlay stack to integrate with. @default the shared `overlayStack` singleton */
111
111
  overlayStack?: GuideOverlayStackLike;
112
- /** Force DEV-mode warnings on/off. @default `import.meta.env.DEV` */
112
+ /** Force DEV-mode warnings on/off. @default `import.meta.env?.DEV ?? false` */
113
113
  dev?: boolean;
114
114
  }
115
115
  /**
@@ -112,7 +112,10 @@ export class GuideController {
112
112
  constructor(options = {}) {
113
113
  this.#storage = options.storage ?? createLocalStorageAdapter();
114
114
  this.#overlayStack = options.overlayStack ?? overlayStack;
115
- this.#dev = options.dev ?? import.meta.env.DEV;
115
+ // `import.meta.env?.DEV` is `boolean | undefined` (undefined outside Vite);
116
+ // `?? false` keeps `#dev` a strict boolean and means non-Vite consumers
117
+ // simply get no dev warnings (rather than a crash).
118
+ this.#dev = options.dev ?? import.meta.env?.DEV ?? false;
116
119
  this.#seen = new SvelteSet(this.#storage.load());
117
120
  }
118
121
  // ─── Target registry ──────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urbicon-ui/blocks",
3
- "version": "6.3.15",
3
+ "version": "6.4.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": {
@@ -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.3.15",
95
- "@urbicon-ui/shared-types": "6.3.15",
94
+ "@urbicon-ui/i18n": "6.4.1",
95
+ "@urbicon-ui/shared-types": "6.4.1",
96
96
  "prettier": "^3.8.4",
97
97
  "prettier-plugin-svelte": "^4.1.1",
98
98
  "prettier-plugin-tailwindcss": "^0.8.0",