@stackloop/ui 3.3.5 → 4.0.2

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.

Potentially problematic release.


This version of @stackloop/ui might be problematic. Click here for more details.

package/README.md CHANGED
@@ -165,6 +165,33 @@ Components with the `animate` prop:
165
165
 
166
166
  - `AudioRecorder`, `Badge`, `BottomSheet`, `Button`, `Card`, `CameraCapture`, `Checkbox`, `CountrySelect`, `DatePicker`, `Drawer`, `Dropdown`, `DualSlider`, `FileUploader`, `FloatingActionButton`, `Input`, `Modal`, `Pagination`, `PhoneInput`, `RadioPills`, `Select`, `Slider`, `Spinner`, `StepProgress`, `Table`, `Textarea`, `ThumbnailGrid`, `Toggle`, `ToastProvider`
167
167
 
168
+ ## Ripple Behavior
169
+
170
+ Ripple effects are **opt-in**. Initialize them once in your app entry file.
171
+
172
+ ```tsx
173
+ // main.tsx or index.tsx
174
+ import { setupRippleEffects } from '@stackloop/ui'
175
+
176
+ setupRippleEffects()
177
+ ```
178
+
179
+ After setup, ripple can apply to interactive elements (`button`, `a`, `[role="button"]`, and elements with `data-ripple="true"`).
180
+
181
+ - Disable ripple for a specific element:
182
+
183
+ ```html
184
+ <button data-ripple="false">No ripple</button>
185
+ ```
186
+
187
+ - Force ripple on a custom/non-button element:
188
+
189
+ ```html
190
+ <div role="button" data-ripple="true">Ripple enabled</div>
191
+ ```
192
+
193
+ Call `setupRippleEffects()` only once per app (for example in `main.tsx`) to avoid duplicate global listeners.
194
+
168
195
  **Checkbox**:
169
196
  - **Description:** Accessible checkbox with optional label and description.
170
197
  - **Props:**
@@ -199,16 +226,25 @@ Components with the `animate` prop:
199
226
  ```
200
227
 
201
228
  **Input**:
202
- - **Description:** Text input with label, error and optional icons. Includes automatic password visibility toggle for password inputs.
229
+ - **Description:** Unified input API with smart type routing. Supports native text/password/email/etc plus `phone`, `country`, and `date` while keeping a consistent `value` + `onChange` pattern.
203
230
  - **Props:**
231
+ - **`type`**: Native HTML input types plus `'phone' | 'country'`.
232
+ - `type="date"` renders the library `DatePicker`.
233
+ - `type="country"` renders `CountrySelect`.
234
+ - `type="phone"` renders `PhoneInput`.
235
+ - **`value`**: `string | number | readonly string[] | Date`.
236
+ - **`onChange`**: `(value: string | Date) => void` — value-based callback used consistently across smart/native modes.
237
+ - **`onValueChange`**: `(value: string | Date) => void` — optional backward-compatible alias.
204
238
  - **`label`**: `string` — optional.
205
239
  - **`error`**: `string` — optional.
206
240
  - **`hint`**: `string` — optional.
207
241
  - **`leftIcon`** / **`rightIcon`**: `ReactNode` — optional.
208
242
  - **`className`**: `string` — optional.
209
- - Inherits `input` HTML attributes.
243
+ - Inherits most `input` HTML attributes.
210
244
  - **Features:**
211
245
  - **Password Toggle:** When `type="password"`, automatically displays an Eye/EyeOff icon to toggle password visibility. This overrides any custom `rightIcon`.
246
+ - **Consistent Value API:** Same controlled pattern for text, phone, country, and date.
247
+ - **Lightweight Composition:** Smart types reuse existing specialized components instead of duplicating logic.
212
248
  - **Icon Support:** Display icons on left or right side of input
213
249
  - **Validation:** Built-in error and hint display
214
250
  - **Accessibility:** Proper labels and ARIA attributes
@@ -221,6 +257,32 @@ Components with the `animate` prop:
221
257
 
222
258
  // Password with automatic toggle
223
259
  <Input label="Password" type="password" placeholder="Enter password" />
260
+
261
+ // Phone (single combined value)
262
+ <Input
263
+ label="Phone"
264
+ type="phone"
265
+ value={phone}
266
+ onChange={(nextValue) => setPhone(String(nextValue))}
267
+ />
268
+
269
+ // Country
270
+ <Input
271
+ label="Country"
272
+ type="country"
273
+ value={country}
274
+ onChange={(nextValue) => setCountry(String(nextValue))}
275
+ />
276
+
277
+ // Date
278
+ <Input
279
+ label="Date"
280
+ type="date"
281
+ value={selectedDate}
282
+ onChange={(nextValue) => {
283
+ if (nextValue instanceof Date) setSelectedDate(nextValue)
284
+ }}
285
+ />
224
286
 
225
287
  // With icons
226
288
  <Input
@@ -231,10 +293,10 @@ Components with the `animate` prop:
231
293
  ```
232
294
 
233
295
  **PhoneInput**:
234
- - **Description:** Phone number input with a country calling code selector and optional locale-based default.
296
+ - **Description:** Phone input with country selector and a single editable value field (country code + number in the same input).
235
297
  - **Props:**
236
298
  - **`value`**: `string` — optional.
237
- - **`onChange`**: `(dialCode: string, value: string) => void` — optional.
299
+ - **`onChange`**: `(value: string) => void` — optional.
238
300
  - **`country`**: `string` — optional ISO2 override (e.g. `US`).
239
301
  - **`defaultCountry`**: `string` — default: `'US'`.
240
302
  - **`autoDetect`**: `boolean` — default: `true`. Uses `navigator.language` to select a country.
@@ -248,6 +310,10 @@ Components with the `animate` prop:
248
310
  - **`animate`**: `boolean` — default: `true`.
249
311
  - **`className`**: `string` — optional.
250
312
  - Inherits standard `input` HTML attributes.
313
+ - **Behavior:**
314
+ - Default selected country auto-fills dial code when the input is empty.
315
+ - User can edit/delete the dial code directly in the same input.
316
+ - Dropdown opens up or down based on available viewport space.
251
317
  - **Usage:**
252
318
 
253
319
  ```jsx
@@ -256,7 +322,7 @@ Components with the `animate` prop:
256
322
  <PhoneInput
257
323
  label="Phone"
258
324
  value={phone}
259
- onChange={(dialCode, value) => setPhone(`${dialCode}${value}`)}
325
+ onChange={setPhone}
260
326
  required
261
327
  hint="Include area code"
262
328
  searchable
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ interface FloatingPortalProps {
3
+ open: boolean;
4
+ anchorRef: React.RefObject<HTMLElement | null>;
5
+ placement: 'top' | 'bottom';
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ offset?: number;
9
+ matchWidth?: boolean;
10
+ }
11
+ export declare const FloatingPortal: React.FC<FloatingPortalProps>;
12
+ export {};
package/dist/Input.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import React from 'react';
2
- export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
2
+ type SmartInputType = React.HTMLInputTypeAttribute | 'country' | 'phone';
3
+ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'value' | 'onChange'> {
4
+ type?: SmartInputType;
5
+ value?: string | number | readonly string[] | Date;
6
+ onChange?: (value: string | Date) => void;
7
+ onValueChange?: (value: string | Date) => void;
3
8
  label?: string;
4
9
  error?: string;
5
10
  hint?: string;
@@ -8,3 +13,4 @@ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement>
8
13
  animate?: boolean;
9
14
  }
10
15
  export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
16
+ export {};
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { type Country } from './countries';
3
3
  export interface PhoneInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> {
4
4
  value?: string;
5
- onChange?: (dialCode: string, value: string) => void;
5
+ onChange?: (value: string) => void;
6
6
  country?: string;
7
7
  defaultCountry?: string;
8
8
  autoDetect?: boolean;
package/dist/Toast.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- export type ToastVariant = 'success' | 'error' | 'warning' | 'info' | 'default';
2
+ export type ToastVariant = 'success' | 'error' | 'warning' | 'info' | 'default' | 'loading';
3
3
  export type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
4
4
  export interface Toast {
5
5
  id: string;