@joewinke/jatui 0.2.13 → 0.2.17

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.
@@ -183,10 +183,19 @@
183
183
  const flipUp = spaceBelow < estPanelHeight && spaceAbove > spaceBelow;
184
184
  // Clamp left so a right-edge trigger doesn't push the panel off-screen.
185
185
  const left = Math.max(8, Math.min(rect.left, window.innerWidth - width - 8));
186
+ // .sd-panel's class rule always sets `top: 100%`, so each branch must
187
+ // explicitly reset the property it isn't using — otherwise the flip-up
188
+ // branch ends up with both top (100% = viewport height) and bottom set
189
+ // while height is auto, which over-constrains to a negative (clamped
190
+ // to 0) height and the whole panel silently renders invisible.
186
191
  const vertical = flipUp
187
- ? `bottom: ${window.innerHeight - rect.top + 4}px;`
188
- : `top: ${rect.bottom + 4}px;`;
189
- panelStyle = `position: fixed; z-index: 9999; ${vertical} left: ${left}px; width: ${width}px; margin-top: 0;`;
192
+ ? `bottom: ${window.innerHeight - rect.top + 4}px; top: auto;`
193
+ : `top: ${rect.bottom + 4}px; bottom: auto;`;
194
+ // min-width override is required: .sd-panel's class rule sets
195
+ // `min-width: max(100%, 14rem)`, and for a position:fixed element
196
+ // that 100% resolves against the viewport, not the trigger — without
197
+ // this override the panel balloons to ~100vw wide.
198
+ panelStyle = `position: fixed; z-index: 9999; ${vertical} left: ${left}px; width: ${width}px; min-width: ${width}px; margin-top: 0;`;
190
199
  }
191
200
  document.addEventListener('mousedown', handleClickOutside);
192
201
  tick().then(() => { searchInput?.focus(); scrollHighlightedIntoView(); });
@@ -14,14 +14,22 @@
14
14
  slots,
15
15
  loading = false,
16
16
  onSelect,
17
+ selectedSlot = null,
17
18
  accentColor = 'primary',
18
19
  }: {
19
20
  slots: TimeSlot[];
20
21
  loading?: boolean;
21
22
  onSelect: (slot: TimeSlot) => void;
23
+ /** The currently-selected slot — rendered with an active highlight.
24
+ * Compared by start-time value (not object identity) so a re-fetched
25
+ * slots array still matches the selection. */
26
+ selectedSlot?: TimeSlot | null;
22
27
  accentColor?: string;
23
28
  } = $props();
24
29
 
30
+ const isSelected = (slot: TimeSlot): boolean =>
31
+ selectedSlot != null && slot.start.getTime() === selectedSlot.start.getTime();
32
+
25
33
  const groupedSlots = $derived(() => {
26
34
  const morning: TimeSlot[] = [];
27
35
  const afternoon: TimeSlot[] = [];
@@ -97,7 +105,9 @@
97
105
  disabled={!slot.available}
98
106
  class="py-3 px-4 rounded-lg text-[0.9375rem] font-medium transition-all duration-200
99
107
  {slot.available
100
- ? `bg-base-200/50 hover:bg-${accentColor} hover:text-${accentColor}-content`
108
+ ? isSelected(slot)
109
+ ? `bg-${accentColor} text-${accentColor}-content ring-2 ring-${accentColor} ring-offset-2 ring-offset-base-100 font-semibold`
110
+ : `bg-base-200/50 hover:bg-${accentColor} hover:text-${accentColor}-content`
101
111
  : 'bg-base-200/20 text-base-content/30 cursor-not-allowed line-through'}"
102
112
  >
103
113
  {formatTime(slot.start)}
@@ -122,7 +132,9 @@
122
132
  disabled={!slot.available}
123
133
  class="py-3 px-4 rounded-lg text-[0.9375rem] font-medium transition-all duration-200
124
134
  {slot.available
125
- ? `bg-base-200/50 hover:bg-${accentColor} hover:text-${accentColor}-content`
135
+ ? isSelected(slot)
136
+ ? `bg-${accentColor} text-${accentColor}-content ring-2 ring-${accentColor} ring-offset-2 ring-offset-base-100 font-semibold`
137
+ : `bg-base-200/50 hover:bg-${accentColor} hover:text-${accentColor}-content`
126
138
  : 'bg-base-200/20 text-base-content/30 cursor-not-allowed line-through'}"
127
139
  >
128
140
  {formatTime(slot.start)}
@@ -148,7 +160,9 @@
148
160
  disabled={!slot.available}
149
161
  class="py-3 px-4 rounded-lg text-[0.9375rem] font-medium transition-all duration-200
150
162
  {slot.available
151
- ? `bg-base-200/50 hover:bg-${accentColor} hover:text-${accentColor}-content`
163
+ ? isSelected(slot)
164
+ ? `bg-${accentColor} text-${accentColor}-content ring-2 ring-${accentColor} ring-offset-2 ring-offset-base-100 font-semibold`
165
+ : `bg-base-200/50 hover:bg-${accentColor} hover:text-${accentColor}-content`
152
166
  : 'bg-base-200/20 text-base-content/30 cursor-not-allowed line-through'}"
153
167
  >
154
168
  {formatTime(slot.start)}
@@ -9,6 +9,10 @@ type $$ComponentProps = {
9
9
  slots: TimeSlot[];
10
10
  loading?: boolean;
11
11
  onSelect: (slot: TimeSlot) => void;
12
+ /** The currently-selected slot — rendered with an active highlight.
13
+ * Compared by start-time value (not object identity) so a re-fetched
14
+ * slots array still matches the selection. */
15
+ selectedSlot?: TimeSlot | null;
12
16
  accentColor?: string;
13
17
  };
14
18
  declare const TimeSlotPicker: import("svelte").Component<$$ComponentProps, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joewinke/jatui",
3
- "version": "0.2.13",
3
+ "version": "0.2.17",
4
4
  "private": false,
5
5
  "description": "Shared Svelte 5 component library for JAT projects",
6
6
  "type": "module",
@@ -67,10 +67,10 @@
67
67
  "build": "vite build",
68
68
  "build:site": "npm run package && vite build",
69
69
  "preview": "vite preview",
70
- "package": "svelte-kit sync && svelte-package --input src/lib --output dist && node scripts/compile-rune-modules.mjs && node scripts/verify-dist.mjs",
71
- "test:dist": "vitest run --config vitest.dist.config.ts",
70
+ "package": "svelte-package --input src/lib --output dist && node scripts/compile-rune-modules.mjs",
72
71
  "check:demos": "node scripts/check-demo-coverage.mjs",
73
72
  "guard": "node scripts/check-demo-coverage.mjs",
73
+ "test:dist": "vitest run --config vitest.dist.config.ts",
74
74
  "prepublishOnly": "node scripts/guard-ci-publish.mjs && npm run package"
75
75
  },
76
76
  "peerDependencies": {
@@ -159,10 +159,7 @@
159
159
  "svelte": "^5.0.0",
160
160
  "tailwindcss": "^4.0.0",
161
161
  "typescript": "^5.0.0",
162
- "vite": "^6.0.0",
163
- "@vitest/browser": "^3.2.0",
164
- "playwright": "^1.53.0",
165
- "vitest": "^3.2.0"
162
+ "vite": "^6.0.0"
166
163
  },
167
164
  "dependencies": {
168
165
  "diff": "^9.0.0",