@stackloop/ui 3.3.4 → 4.0.3
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.
- package/README.md +106 -8
- package/dist/CountrySelect.d.ts +3 -0
- package/dist/DatePicker.d.ts +2 -0
- package/dist/FloatingPortal.d.ts +12 -0
- package/dist/Input.d.ts +7 -1
- package/dist/PhoneInput.d.ts +1 -1
- package/dist/Toast.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2867 -2374
- package/dist/index.js.map +1 -1
- package/dist/ripple.d.ts +6 -0
- package/dist/stackloop-ui.css +1 -1
- package/package.json +1 -1
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:**
|
|
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,18 +293,27 @@ Components with the `animate` prop:
|
|
|
231
293
|
```
|
|
232
294
|
|
|
233
295
|
**PhoneInput**:
|
|
234
|
-
- **Description:** Phone
|
|
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`**: `(
|
|
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.
|
|
241
303
|
- **`onCountryChange`**: `(country: Country) => void` — optional.
|
|
304
|
+
- **`label`**: `string` — optional.
|
|
305
|
+
- **`required`**: `boolean` — optional. Shows a required marker (`*`) on label and passes `required` to the inner input.
|
|
306
|
+
- **`error`**: `string` — optional. Shows error state and helper text.
|
|
307
|
+
- **`hint`**: `string` — optional. Shown only when `error` is not present.
|
|
242
308
|
- **`searchable`**: `boolean` — default: `true`.
|
|
243
309
|
- **`showFlags`**: `boolean` — default: `true`.
|
|
244
310
|
- **`animate`**: `boolean` — default: `true`.
|
|
311
|
+
- **`className`**: `string` — optional.
|
|
245
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.
|
|
246
317
|
- **Usage:**
|
|
247
318
|
|
|
248
319
|
```jsx
|
|
@@ -251,7 +322,9 @@ Components with the `animate` prop:
|
|
|
251
322
|
<PhoneInput
|
|
252
323
|
label="Phone"
|
|
253
324
|
value={phone}
|
|
254
|
-
onChange={
|
|
325
|
+
onChange={setPhone}
|
|
326
|
+
required
|
|
327
|
+
hint="Include area code"
|
|
255
328
|
searchable
|
|
256
329
|
autoDetect
|
|
257
330
|
/>
|
|
@@ -264,11 +337,16 @@ Components with the `animate` prop:
|
|
|
264
337
|
- **`onChange`**: `(value: string) => void` — optional.
|
|
265
338
|
- **`onCountryChange`**: `(country: Country) => void` — optional.
|
|
266
339
|
- **`label`**: `string` — optional.
|
|
340
|
+
- **`required`**: `boolean` — optional. Shows a required marker (`*`) and `aria-required` on trigger.
|
|
267
341
|
- **`placeholder`**: `string` — optional.
|
|
342
|
+
- **`error`**: `string` — optional. Adds error border/ring and error message.
|
|
343
|
+
- **`hint`**: `string` — optional. Shown only when `error` is not present.
|
|
268
344
|
- **`searchable`**: `boolean` — default: `true`.
|
|
269
345
|
- **`clearable`**: `boolean` — default: `true`.
|
|
270
346
|
- **`showFlags`**: `boolean` — default: `true`.
|
|
347
|
+
- **`disabled`**: `boolean` — optional.
|
|
271
348
|
- **`animate`**: `boolean` — default: `true`.
|
|
349
|
+
- **`className`**: `string` — optional.
|
|
272
350
|
- **Usage:**
|
|
273
351
|
|
|
274
352
|
```jsx
|
|
@@ -278,6 +356,8 @@ Components with the `animate` prop:
|
|
|
278
356
|
label="Country"
|
|
279
357
|
value={country}
|
|
280
358
|
onChange={setCountry}
|
|
359
|
+
required
|
|
360
|
+
hint="Used for regional formatting"
|
|
281
361
|
searchable
|
|
282
362
|
/>
|
|
283
363
|
```
|
|
@@ -644,17 +724,35 @@ Components with the `animate` prop:
|
|
|
644
724
|
```
|
|
645
725
|
|
|
646
726
|
**DatePicker**:
|
|
647
|
-
- **Description:** Date picker with
|
|
727
|
+
- **Description:** Date picker with day grid, min/max date constraints, and fast custom month/year pickers.
|
|
648
728
|
- **Props:**
|
|
649
729
|
- **`value`**: `Date` — optional.
|
|
650
730
|
- **`onChange`**: `(date: Date) => void` — required.
|
|
651
|
-
- **`label
|
|
731
|
+
- **`label`**: `string` — optional.
|
|
732
|
+
- **`required`**: `boolean` — optional. Shows required marker (`*`) and `aria-required`.
|
|
733
|
+
- **`placeholder`**: `string` — default: `'Select date'`.
|
|
734
|
+
- **`error`**: `string` — optional.
|
|
735
|
+
- **`hint`**: `string` — optional. Shown only when `error` is not present.
|
|
736
|
+
- **`disabled`**: `boolean` — optional.
|
|
737
|
+
- **`minDate`** / **`maxDate`**: `Date` — optional.
|
|
738
|
+
- **`animate`**: `boolean` — default: `true`.
|
|
739
|
+
- **`className`**: `string` — optional.
|
|
740
|
+
- **Features:**
|
|
741
|
+
- **Custom Month Menu:** Scrollable month dropdown/dropup (no native browser select).
|
|
742
|
+
- **Custom Year Menu:** Scrollable year dropdown/dropup that supports quick jumps across many years.
|
|
743
|
+
- **Adaptive Positioning:** Month/year menus open upward when there is insufficient viewport space below.
|
|
652
744
|
- **Usage:**
|
|
653
745
|
|
|
654
746
|
```jsx
|
|
655
747
|
import { DatePicker } from '@stackloop/ui'
|
|
656
748
|
|
|
657
|
-
<DatePicker
|
|
749
|
+
<DatePicker
|
|
750
|
+
label="Date of birth"
|
|
751
|
+
value={date}
|
|
752
|
+
onChange={setDate}
|
|
753
|
+
required
|
|
754
|
+
hint="Choose month/year quickly from the menu"
|
|
755
|
+
/>
|
|
658
756
|
```
|
|
659
757
|
|
|
660
758
|
**DualSlider**:
|
package/dist/CountrySelect.d.ts
CHANGED
|
@@ -5,7 +5,10 @@ export interface CountrySelectProps {
|
|
|
5
5
|
onChange?: (value: string) => void;
|
|
6
6
|
onCountryChange?: (country: Country) => void;
|
|
7
7
|
label?: string;
|
|
8
|
+
required?: boolean;
|
|
8
9
|
placeholder?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
hint?: string;
|
|
9
12
|
searchable?: boolean;
|
|
10
13
|
clearable?: boolean;
|
|
11
14
|
showFlags?: boolean;
|
package/dist/DatePicker.d.ts
CHANGED
|
@@ -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
|
-
|
|
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 {};
|
package/dist/PhoneInput.d.ts
CHANGED
|
@@ -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?: (
|
|
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;
|