@ahrowe/ui 0.12.0 → 0.13.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 (45) hide show
  1. package/dist/esm/common/alert/alert.mjs +2 -0
  2. package/dist/esm/common/alert/alert.mjs.map +1 -0
  3. package/dist/esm/common/alert/alert.module.mjs +2 -0
  4. package/dist/esm/common/alert/alert.module.mjs.map +1 -0
  5. package/dist/esm/common/alert/alert.types.mjs +2 -0
  6. package/dist/esm/common/alert/alert.types.mjs.map +1 -0
  7. package/dist/esm/common/breadcrumb/breadcrumb.mjs +2 -0
  8. package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -0
  9. package/dist/esm/common/breadcrumb/breadcrumb.module.mjs +2 -0
  10. package/dist/esm/common/breadcrumb/breadcrumb.module.mjs.map +1 -0
  11. package/dist/esm/common/carousel/carousel.mjs +2 -0
  12. package/dist/esm/common/carousel/carousel.mjs.map +1 -0
  13. package/dist/esm/common/carousel/carousel.module.mjs +2 -0
  14. package/dist/esm/common/carousel/carousel.module.mjs.map +1 -0
  15. package/dist/esm/common/klipyPicker/klipyPicker.mjs +1 -1
  16. package/dist/esm/common/rating/rating.mjs +2 -0
  17. package/dist/esm/common/rating/rating.mjs.map +1 -0
  18. package/dist/esm/common/rating/rating.module.mjs +2 -0
  19. package/dist/esm/common/rating/rating.module.mjs.map +1 -0
  20. package/dist/esm/common/virtualList/virtualList.mjs +1 -1
  21. package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
  22. package/dist/esm/index.mjs +1 -1
  23. package/dist/index.cjs +4 -4
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/style.css +1 -1
  26. package/dist/types/package/common/alert/alert.d.ts +4 -0
  27. package/dist/types/package/common/alert/alert.types.d.ts +23 -0
  28. package/dist/types/package/common/alert/index.d.ts +2 -0
  29. package/dist/types/package/common/breadcrumb/breadcrumb.d.ts +4 -0
  30. package/dist/types/package/common/breadcrumb/breadcrumb.types.d.ts +26 -0
  31. package/dist/types/package/common/breadcrumb/index.d.ts +2 -0
  32. package/dist/types/package/common/carousel/carousel.d.ts +3 -0
  33. package/dist/types/package/common/carousel/carousel.types.d.ts +20 -0
  34. package/dist/types/package/common/carousel/index.d.ts +2 -0
  35. package/dist/types/package/common/configProvider/configProvider.types.d.ts +8 -0
  36. package/dist/types/package/common/rating/index.d.ts +2 -0
  37. package/dist/types/package/common/rating/rating.d.ts +4 -0
  38. package/dist/types/package/common/rating/rating.types.d.ts +19 -0
  39. package/dist/types/package/index.d.ts +8 -0
  40. package/docs/Alert.md +64 -0
  41. package/docs/Breadcrumb.md +106 -0
  42. package/docs/CLAUDE.md +4 -0
  43. package/docs/Carousel.md +67 -0
  44. package/docs/Rating.md +72 -0
  45. package/package.json +1 -1
package/docs/Alert.md ADDED
@@ -0,0 +1,64 @@
1
+ # Alert
2
+
3
+ **When to use:** A persistent inline status message, used for form-level errors, page/section banners, empty-config warnings, and "here's what changed" notices. Unlike `Toast`, it isn't portaled or auto-dismissed, and it stays in the page's normal flow for as long as its consumer renders it. Use `Toast` instead for a transient, corner-anchored notification.
4
+
5
+ **Import:** `import { Alert, AlertStyleType } from '@ahrowe/ui'`
6
+
7
+ **Style variants:** `AlertStyleType.Default` | `AlertStyleType.Info` | `AlertStyleType.Success` | `AlertStyleType.Warn` | `AlertStyleType.Error`
8
+
9
+ ```tsx
10
+ import { Alert, AlertStyleType } from '@ahrowe/ui';
11
+
12
+ // Default, neutral message
13
+ <Alert>A default, neutral message.</Alert>
14
+
15
+ // Semantic variants
16
+ <Alert styleType={AlertStyleType.Info}>Here's something worth knowing.</Alert>
17
+ <Alert styleType={AlertStyleType.Success}>Your changes were saved.</Alert>
18
+ <Alert styleType={AlertStyleType.Warn}>Your storage is almost full.</Alert>
19
+ <Alert styleType={AlertStyleType.Error}>Something went wrong. Please try again.</Alert>
20
+
21
+ // With a title
22
+ <Alert styleType={AlertStyleType.Warn} title="Storage almost full">
23
+ You've used 92% of your available space. Free up room or upgrade your plan.
24
+ </Alert>
25
+
26
+ // Dismissible: the consumer owns visibility. onClose is called on click,
27
+ // so stop rendering the Alert (or flip your own state) to actually hide it
28
+ const [visible, setVisible] = useState(true);
29
+ {visible && (
30
+ <Alert
31
+ styleType={AlertStyleType.Info}
32
+ title="New feature available"
33
+ onClose={() => setVisible(false)}
34
+ >
35
+ Try out the new dashboard layout from your account settings.
36
+ </Alert>
37
+ )}
38
+
39
+ // Without the leading icon
40
+ <Alert styleType={AlertStyleType.Success} hideIcon>
41
+ A minimal message with no leading icon.
42
+ </Alert>
43
+
44
+ // Custom icon, overriding the styleType default
45
+ import { faRocket } from '@fortawesome/free-solid-svg-icons';
46
+ <Alert styleType={AlertStyleType.Info} icon={faRocket}>
47
+ Shipping a new release tonight.
48
+ </Alert>
49
+ ```
50
+
51
+ **Key props:**
52
+
53
+ | Prop | Type | Description |
54
+ |------|------|-------------|
55
+ | `title` | `ReactNode` | Optional bold heading above the description |
56
+ | `children` | `ReactNode` | The message body |
57
+ | `styleType` | `AlertStyleType` | Colour variant and default icon (default `Default`) |
58
+ | `icon` | `IconDefinition` | Overrides the default FontAwesome icon for `styleType` |
59
+ | `hideIcon` | `boolean` | Hide the leading icon entirely |
60
+ | `onClose` | `() => void` | Shows a close button and is called when it's clicked. `Alert` doesn't hide itself, so stop rendering it (or update your own state) in the handler |
61
+
62
+ **Global defaults:** adopts `ConfigProvider`, e.g. `defaultProps={{ Alert: { hideIcon: true } }}`. See [ConfigProvider.md](ConfigProvider.md).
63
+
64
+ **Slots:** `root` `icon` `content` `title` `description` `closeButton`
@@ -0,0 +1,106 @@
1
+ # Breadcrumb
2
+
3
+ **When to use:** A trail showing the current page's position within a hierarchy, with links back to each ancestor, such as a file browser path, a category/subcategory drill-down, or a multi-level settings page. The last item is always rendered as the current page and isn't clickable.
4
+
5
+ **Import:** `import { Breadcrumb } from '@ahrowe/ui'`
6
+ **Types:** `import type { BreadcrumbItem, BreadcrumbProps } from '@ahrowe/ui'`
7
+
8
+ ```tsx
9
+ import { Breadcrumb } from '@ahrowe/ui';
10
+ import type { BreadcrumbItem } from '@ahrowe/ui';
11
+
12
+ const items: BreadcrumbItem[] = [
13
+ { label: 'Home', href: '/' },
14
+ { label: 'Documents', href: '/documents' },
15
+ { label: 'Report.pdf' }, // last item: rendered as the current page, not a link
16
+ ];
17
+
18
+ <Breadcrumb items={items} />
19
+
20
+ // With leading icons
21
+ import { faHouse, faFolder } from '@fortawesome/free-solid-svg-icons';
22
+
23
+ <Breadcrumb
24
+ items={[
25
+ { label: 'Home', href: '/', icon: faHouse },
26
+ { label: 'Projects', href: '/projects', icon: faFolder },
27
+ { label: 'Current project' },
28
+ ]}
29
+ />
30
+
31
+ // Client-side routing (e.g. react-router): keep href for a real, right-clickable link,
32
+ // and use onClick to intercept the native navigation with the router's own navigate()
33
+ import { useNavigate } from 'react-router-dom';
34
+
35
+ function Example() {
36
+ const navigate = useNavigate();
37
+ return (
38
+ <Breadcrumb
39
+ items={[
40
+ {
41
+ label: 'Home',
42
+ href: '/',
43
+ onClick: (event) => {
44
+ event.preventDefault();
45
+ navigate('/');
46
+ },
47
+ },
48
+ { label: 'Current page' },
49
+ ]}
50
+ />
51
+ );
52
+ }
53
+
54
+ // A disabled crumb: dimmed, not clickable, regardless of href/onClick
55
+ <Breadcrumb
56
+ items={[
57
+ { label: 'Home', href: '/' },
58
+ { label: 'Archived', href: '/archived', disabled: true },
59
+ { label: 'Old report' },
60
+ ]}
61
+ />
62
+
63
+ // Custom separator (default is a chevron icon)
64
+ <Breadcrumb items={items} separator="/" />
65
+
66
+ // Long trails: collapse the middle behind a clickable ellipsis once items.length
67
+ // exceeds maxItems. The ellipsis counts as one of the visible slots, so maxItems={3}
68
+ // on a 4-item trail shows: Home / ... / Settings. Clicking the ellipsis opens a menu
69
+ // (via FloatingMenu) listing the hidden items.
70
+ <Breadcrumb
71
+ items={[
72
+ { label: 'Home', href: '/' },
73
+ { label: 'Invoices', href: '/invoices' },
74
+ { label: 'Editor', href: '/invoices/editor' },
75
+ { label: 'Settings' },
76
+ ]}
77
+ maxItems={3}
78
+ />
79
+ ```
80
+
81
+ **Requires:** `<div id="bodyEnd"></div>` in your HTML when `maxItems` is used and the trail actually collapses (the hidden-items menu is a `FloatingMenu`, which renders via portal).
82
+
83
+ **BreadcrumbItem:**
84
+
85
+ | Field | Type | Description |
86
+ |-------|------|-------------|
87
+ | `id` | `string` | Optional stable key; falls back to the item's index |
88
+ | `label` | `ReactNode` | The crumb's text |
89
+ | `href` | `string` | Renders the crumb as a real `<a>`. Omit to render a plain clickable element (with `onClick`) or static text |
90
+ | `icon` | `IconDefinition` | Optional leading FontAwesome icon |
91
+ | `onClick` | `(event: MouseEvent) => void` | Click handler. Works alongside `href`: call `event.preventDefault()` to stop the native navigation and hand off to a client-side router's own navigate function (see the react-router example above). Also works on its own, with no `href` |
92
+ | `disabled` | `boolean` | Dims the crumb and makes it non-interactive, regardless of `href`/`onClick` |
93
+
94
+ **Key props:**
95
+
96
+ | Prop | Type | Description |
97
+ |------|------|-------------|
98
+ | `items` | `BreadcrumbItem[]` | The crumbs, in order. The last one is always rendered as the current page |
99
+ | `separator` | `ReactNode` | Overrides the default chevron separator between items |
100
+ | `maxItems` | `number` | Collapses the middle items behind a clickable ellipsis once `items.length` exceeds this. The ellipsis counts as one of the visible slots, alongside the always-shown first item (so `maxItems={3}` shows first item, ellipsis, last item) |
101
+
102
+ **Collapsing behaviour:** the hidden count grows and shrinks by exactly however many items are actually over the limit, rather than always jumping to the same minimal first/ellipsis/last shape. A trail with 11 items and `maxItems={10}` hides only 2 items, not the whole middle, so the trail doesn't visually lurch as one more level of navigation pushes it just over the limit.
103
+
104
+ **Global defaults:** adopts `ConfigProvider`, e.g. `defaultProps={{ Breadcrumb: { separator: '/' } }}`. See [ConfigProvider.md](ConfigProvider.md).
105
+
106
+ **Slots:** `root` `list` `item` `link` `icon` `separator` `current` `ellipsis` `hiddenList` `hiddenItem`
package/docs/CLAUDE.md CHANGED
@@ -95,13 +95,16 @@ Slot keys per component are documented in each component's doc file below.
95
95
  @Accordion.md
96
96
  @ActionButtons.md
97
97
  @ActionIcon.md
98
+ @Alert.md
98
99
  @AnimatedLogo.md
99
100
  @AnimatedText.md
100
101
  @Avatar.md
101
102
  @Badge.md
102
103
  @BodyEnd.md
104
+ @Breadcrumb.md
103
105
  @Button.md
104
106
  @Card.md
107
+ @Carousel.md
105
108
  @Checkbox.md
106
109
  @Chip.md
107
110
  @ColorPicker.md
@@ -133,6 +136,7 @@ Slot keys per component are documented in each component's doc file below.
133
136
  @Popover.md
134
137
  @ProgressBar.md
135
138
  @RadioGroup.md
139
+ @Rating.md
136
140
  @Ripple.md
137
141
  @RoomDrawer.md
138
142
  @RoomViewer.md
@@ -0,0 +1,67 @@
1
+ # Carousel
2
+
3
+ **When to use:** A slide track for stepping through a set of items one at a time, with arrows, dots, and drag/swipe support, plus optional autoplay. Slides are plain children, so any content works (images, cards, mixed content), not just a fixed image-gallery shape.
4
+
5
+ **Import:** `import { Carousel } from '@ahrowe/ui'`
6
+ **Types:** `import type { CarouselProps } from '@ahrowe/ui'`
7
+
8
+ ```tsx
9
+ import { Carousel } from '@ahrowe/ui';
10
+
11
+ // Uncontrolled, looping by default, with arrows, dots, and swipe all on
12
+ <Carousel>
13
+ <div>Slide 1</div>
14
+ <div>Slide 2</div>
15
+ <div>Slide 3</div>
16
+ </Carousel>
17
+
18
+ // Controlled
19
+ const [index, setIndex] = useState(0);
20
+ <Carousel currentIndex={index} onChange={setIndex}>
21
+ <div>Slide 1</div>
22
+ <div>Slide 2</div>
23
+ <div>Slide 3</div>
24
+ </Carousel>
25
+
26
+ // Autoplay, paused on hover/focus by default, with dots hidden
27
+ <Carousel autoPlay autoPlayInterval={4000} showDots={false}>
28
+ <div>Slide 1</div>
29
+ <div>Slide 2</div>
30
+ </Carousel>
31
+
32
+ // Bounded instead of looping: arrows disable at the first/last slide
33
+ <Carousel loop={false}>
34
+ <div>Slide 1</div>
35
+ <div>Slide 2</div>
36
+ </Carousel>
37
+
38
+ // No swipe/drag, arrows only
39
+ <Carousel swipeable={false} showDots={false}>
40
+ <div>Slide 1</div>
41
+ <div>Slide 2</div>
42
+ </Carousel>
43
+ ```
44
+
45
+ Pass slides as direct children (an array or a set of sibling elements), not through a component that returns a fragment internally. `Carousel` reads its immediate children via `React.Children`, so a wrapper component's own children aren't visible to it. If slides come from a `.map()`, spread the array straight into `Carousel`, the same way `children` normally works in React.
46
+
47
+ **Interaction:** drag or swipe the track to move between slides (committing past roughly 20% of the container's width, or releasing further than that snaps to the next/previous slide; a shorter drag springs back). Left/right arrow keys move between slides when focus is anywhere inside the carousel.
48
+
49
+ **Key props:**
50
+
51
+ | Prop | Type | Description |
52
+ |------|------|-------------|
53
+ | `children` | `ReactNode` | The slides, one per direct child |
54
+ | `currentIndex` | `number` | Controlled active slide index |
55
+ | `defaultIndex` | `number` | Initial active slide index when uncontrolled (default `0`) |
56
+ | `onChange` | `(index: number) => void` | Called whenever the active slide changes, from arrows, dots, keyboard, drag, or autoplay |
57
+ | `loop` | `boolean` | Wrap from the last slide to the first and back (default `true`) |
58
+ | `autoPlay` | `boolean` | Automatically advance on a timer (default `false`) |
59
+ | `autoPlayInterval` | `number` | Autoplay delay in ms (default `4000`) |
60
+ | `pauseOnHover` | `boolean` | Pause autoplay while hovered or focused (default `true`) |
61
+ | `showArrows` | `boolean` | Show the prev/next buttons (default `true`); hidden automatically with one slide or none |
62
+ | `showDots` | `boolean` | Show the position dots (default `true`); hidden automatically with one slide or none |
63
+ | `swipeable` | `boolean` | Allow dragging/swiping the track (default `true`) |
64
+
65
+ **Global defaults:** adopts `ConfigProvider`, e.g. `defaultProps={{ Carousel: { autoPlay: true } }}`. See [ConfigProvider.md](ConfigProvider.md).
66
+
67
+ **Slots:** `root` `track` `slide` `prevButton` `nextButton` `dots` `dot`
package/docs/Rating.md ADDED
@@ -0,0 +1,72 @@
1
+ # Rating
2
+
3
+ **When to use:** A star rating input or display, for review scores, feedback prompts, and quality indicators. Use `readOnly` to just show an existing rating (e.g. a product's average score) rather than collect one.
4
+
5
+ **Import:** `import { Rating } from '@ahrowe/ui'`
6
+ **Types:** `import type { RatingProps } from '@ahrowe/ui'`
7
+
8
+ ```tsx
9
+ import { useState } from 'react';
10
+ import { Rating } from '@ahrowe/ui';
11
+
12
+ // Controlled
13
+ const [value, setValue] = useState(3);
14
+ <Rating value={value} onChange={setValue} />
15
+
16
+ // Uncontrolled
17
+ <Rating defaultValue={4} onChange={(value) => console.log(value)} />
18
+
19
+ // Half-star increments
20
+ <Rating defaultValue={3.5} allowHalf />
21
+
22
+ // A different number of stars
23
+ <Rating defaultValue={6} max={10} />
24
+
25
+ // Read-only, for displaying an existing rating (e.g. a product card)
26
+ <Rating value={4} readOnly />
27
+
28
+ // Disabled
29
+ <Rating value={2} disabled />
30
+
31
+ // Larger, via font-size (sizing is em-based, like Switch and Avatar)
32
+ <Rating defaultValue={4} style={{ fontSize: 32 }} />
33
+
34
+ // Custom icon
35
+ import { faHeart } from '@fortawesome/free-solid-svg-icons';
36
+ <Rating defaultValue={3} icon={faHeart} />
37
+
38
+ // Disable click-to-clear (clicking the currently-selected star normally resets to 0)
39
+ <Rating value={value} onChange={setValue} allowClear={false} />
40
+ ```
41
+
42
+ **Interaction:** click, tap, or drag/swipe across the stars to set the rating, on any pointer type (mouse, touch, pen) via the Pointer Events API. Dragging updates the preview live and commits on release, which is the natural gesture on mobile rather than requiring a precise tap on one star. A plain click/tap on the currently-selected star clears it to `0` (set `allowClear={false}` to keep it fixed instead); a drag that happens to end back near its starting value doesn't clear, since that's a different gesture from a deliberate re-tap. With keyboard focus: `←`/`↓` and `→`/`↑` move by one star (or half a star with `allowHalf`), `Home`/`End` jump to `0`/`max`.
43
+
44
+ **Sizing:** there's no dedicated size prop, `font-size` scales the whole control (like `Switch` and `Avatar`). The root sizes to its content (`width: fit-content`) rather than stretching to fill a flex/grid ancestor, since the click/drag position is measured against the root's own width.
45
+
46
+ **Key props:**
47
+
48
+ | Prop | Type | Description |
49
+ |------|------|-------------|
50
+ | `value` | `number` | Controlled value (omit for uncontrolled) |
51
+ | `defaultValue` | `number` | Initial value when uncontrolled (default `0`) |
52
+ | `onChange` | `(value: number) => void` | Fires when the rating changes, from a click or keyboard input |
53
+ | `max` | `number` | Number of stars (default `5`) |
54
+ | `allowHalf` | `boolean` | Allow half-star increments (default `false`) |
55
+ | `allowClear` | `boolean` | Clicking the currently-selected star resets the value to `0` (default `true`) |
56
+ | `readOnly` | `boolean` | Display only, not focusable or interactive |
57
+ | `disabled` | `boolean` | Dims the control and disables interaction |
58
+ | `icon` | `IconDefinition` | Overrides the default star icon |
59
+ | `aria-label` | `string` | Accessible label (default `'Rating'`) |
60
+
61
+ **Accessibility:** renders `role="slider"` with `aria-valuemin`/`aria-valuemax`/`aria-valuenow`/`aria-valuetext`, matching `Slider`'s pattern.
62
+
63
+ **Theming:** override these CSS variables theme-wide via `ThemeProvider` or per instance via `style`; each falls back to a built-in default:
64
+
65
+ | Variable | Falls back to |
66
+ |----------|---------------|
67
+ | `--rating-filled-color` | `var(--primary-color)` |
68
+ | `--rating-empty-color` | `var(--background-accent-light)` |
69
+
70
+ **Global defaults:** adopts `ConfigProvider`, e.g. `defaultProps={{ Rating: { allowHalf: true } }}`. See [ConfigProvider.md](ConfigProvider.md).
71
+
72
+ **Slots:** `root` `item` `iconEmpty` `iconFilled`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahrowe/ui",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },