polymorph-ui-components-mcp 0.0.1 → 0.2.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.
- package/build/docs/CHANGELOG.md +14 -0
- package/build/docs/Chat.md +211 -0
- package/build/docs/ChatBubble.md +213 -0
- package/build/docs/ChatComposer.md +96 -0
- package/build/docs/ChatHeader.md +74 -0
- package/build/docs/ChatMessage.md +108 -0
- package/build/docs/ChatMessageList.md +63 -0
- package/build/docs/ChatSuggestions.md +52 -0
- package/build/docs/ChatToolStatus.md +47 -0
- package/build/docs/Draggable.md +88 -0
- package/build/docs/GUIDELINES.md +67 -0
- package/build/docs/MediaPlayer.md +93 -0
- package/build/docs/MediaUpload.md +150 -0
- package/build/docs/Resizable.md +94 -0
- package/build/docs/Tabs.md +1 -1
- package/build/docs/_index.json +48 -0
- package/package.json +1 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# MediaUpload
|
|
2
|
+
|
|
3
|
+
A polished file upload field with a drag-and-drop drop zone, inline previews, and validation. Image files render as cover thumbnails (via the `Img` component) with a `Shimmer` placeholder while they load; non-image files render as a card with a file icon, name, and size. Files are validated against `accept` and `maxFileSize` and capped at `maxLength`; rejected files surface an inline, customizable error message. A header row shows the optional label and an `attached / maxLength` counter, and each card reveals a remove button (the `Button` component) on hover. The bindable `files` array plus `onchange`, `onremove`, and `onerror` callbacks expose the current selection. All text is opt-in (no baked-in copy), built-in icons can be swapped via snippet props, and every dimension, color, border, and interaction state is themeable through CSS variables.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```svelte
|
|
8
|
+
<script>
|
|
9
|
+
import { MediaUpload } from 'polymorph-ui-components';
|
|
10
|
+
|
|
11
|
+
let files = $state([]);
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<MediaUpload
|
|
15
|
+
bind:files
|
|
16
|
+
label="Supporting Images"
|
|
17
|
+
hintText="PNG or JPG, up to 5 MB"
|
|
18
|
+
accept="image/*"
|
|
19
|
+
maxFileSize={5 * 1024 * 1024}
|
|
20
|
+
maxLength={4}
|
|
21
|
+
multiple
|
|
22
|
+
/>
|
|
23
|
+
|
|
24
|
+
<!-- Swap an icon with your own markup -->
|
|
25
|
+
<MediaUpload bind:files accept=".pdf,.doc,.docx">
|
|
26
|
+
{#snippet fileIcon()}
|
|
27
|
+
<img src="/icons/document.svg" alt="" />
|
|
28
|
+
{/snippet}
|
|
29
|
+
</MediaUpload>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Props
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Required | Default | Description |
|
|
35
|
+
| ------------- | ------------------------- | -------- | -------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| label | `string` | No | `-` | Heading text shown above the previews. Hidden when omitted. |
|
|
37
|
+
| description | `string` | No | `-` | Helper text under the label. Hidden when omitted. |
|
|
38
|
+
| addText | `string` | No | `-` | Caption inside the drop tile. Hidden when omitted (the tile still shows its icon). |
|
|
39
|
+
| hintText | `string` | No | `-` | Secondary hint inside the drop tile (e.g. accepted formats and size limit). Hidden when omitted. |
|
|
40
|
+
| maxLength | `number` | No | `3` | Maximum number of files. The drop tile hides once reached. |
|
|
41
|
+
| accept | `string` | No | `'image/*'` | Accepted file types. Forwarded to the file input and used to validate dropped files (MIME or extension). |
|
|
42
|
+
| maxFileSize | `number` | No | `0` | Maximum size per file in bytes. `0` disables the size check. |
|
|
43
|
+
| multiple | `boolean` | No | `false` | Allow selecting/dropping more than one file at a time (still capped by `maxLength`). |
|
|
44
|
+
| dragAndDrop | `boolean` | No | `true` | Enable the drag-and-drop drop zone. |
|
|
45
|
+
| disabled | `boolean` | No | `false` | Disable all interaction and dim the component. |
|
|
46
|
+
| showCounter | `boolean` | No | `true` | Show the `attached / maxLength` counter next to the label. |
|
|
47
|
+
| showFileName | `boolean` | No | `true` | Show each file's name on its card. |
|
|
48
|
+
| showFileSize | `boolean` | No | `true` | Show each file's human-readable size on its card. |
|
|
49
|
+
| addIcon | `Snippet` | No | `-` | Snippet rendering a custom drop-tile icon. Falls back to the built-in asset when omitted. |
|
|
50
|
+
| removeIcon | `Snippet` | No | `-` | Snippet rendering a custom remove-button icon. Falls back to the built-in asset when omitted. |
|
|
51
|
+
| fileIcon | `Snippet` | No | `-` | Snippet rendering a custom icon for non-image files. Falls back to the built-in asset when omitted. |
|
|
52
|
+
| errorMessages | `MediaUploadErrorMessages`| No | `-` | Override copy for the `type`, `size`, and `max` validation messages. |
|
|
53
|
+
| files | `File[]` | No | `[]` | Bindable. The list of currently attached files. |
|
|
54
|
+
| testId | `string` | No | `-` | Test selector value applied as `data-pw` on the outermost element. |
|
|
55
|
+
| classes | `string` | No | `-` | CSS class string applied to the top-level element. Useful for theming via CSS variable override classes. |
|
|
56
|
+
|
|
57
|
+
## Events
|
|
58
|
+
|
|
59
|
+
| Event | Type | Description |
|
|
60
|
+
| -------- | ------------------------------------------- | ----------------------------------------------------------------------- |
|
|
61
|
+
| onchange | `(files: File[]) => void` | Fires after a file is added or removed, with the updated files array. |
|
|
62
|
+
| onremove | `(file: File) => void` | Fires when a single file is removed, with the removed file. |
|
|
63
|
+
| onerror | `(rejections: MediaUploadRejection[]) => void` | Fires when files are rejected, each with a `'type' \| 'size' \| 'max'` reason. |
|
|
64
|
+
|
|
65
|
+
## CSS Variables
|
|
66
|
+
|
|
67
|
+
Override these custom properties to theme the component.
|
|
68
|
+
|
|
69
|
+
| Variable | Default | CSS Property | Description |
|
|
70
|
+
| ---------------------------------------------- | ---------------------------------------------------- | ---------------- | -------------------------------------------- |
|
|
71
|
+
| `--media-upload-width` | `fit-content` | width | Width of the component. |
|
|
72
|
+
| `--media-upload-font-family` | `inherit` | font-family | Font family of all text. |
|
|
73
|
+
| `--media-upload-color` | `inherit` | color | Base text color. |
|
|
74
|
+
| `--media-upload-disabled-opacity` | `0.55` | opacity | Opacity when `disabled`. |
|
|
75
|
+
| `--media-upload-header-gap` | `12px` | gap | Gap between label and counter. |
|
|
76
|
+
| `--media-upload-label-margin` | `0 0 4px 0` | margin | Margin around the header row. |
|
|
77
|
+
| `--media-upload-label-font-size` | `14px` | font-size | Font size of the label. |
|
|
78
|
+
| `--media-upload-label-font-weight` | `600` | font-weight | Weight of the label. |
|
|
79
|
+
| `--media-upload-label-color` | `#242833` | color | Color of the label. |
|
|
80
|
+
| `--media-upload-counter-font-size` | `12px` | font-size | Font size of the counter. |
|
|
81
|
+
| `--media-upload-counter-font-weight` | `500` | font-weight | Weight of the counter. |
|
|
82
|
+
| `--media-upload-counter-color` | `#8a8f98` | color | Color of the counter. |
|
|
83
|
+
| `--media-upload-description-font-size` | `12px` | font-size | Font size of the helper description. |
|
|
84
|
+
| `--media-upload-description-color` | `#656565` | color | Color of the helper description. |
|
|
85
|
+
| `--media-upload-description-margin` | `0` | margin | Margin around the helper description. |
|
|
86
|
+
| `--media-upload-gap` | `12px` | gap | Gap between cards and the drop tile. |
|
|
87
|
+
| `--media-upload-content-margin` | `12px 0 0 0` | margin | Margin above the grid. |
|
|
88
|
+
| `--media-upload-item-height` | `110px` | height | Height of each card/drop tile. |
|
|
89
|
+
| `--media-upload-item-width` | `110px` | width | Width of each card/drop tile. |
|
|
90
|
+
| `--media-upload-item-border-radius` | `14px` | border-radius | Corner rounding of cards/drop tile. |
|
|
91
|
+
| `--media-upload-item-border` | `1px solid #e4e4e7` | border | Border of each preview card. |
|
|
92
|
+
| `--media-upload-item-background-color` | `#fafafa` | background-color | Background of each preview card. |
|
|
93
|
+
| `--media-upload-item-box-shadow` | `0 1px 2px rgba(0,0,0,0.06)` | box-shadow | Resting shadow of each card. |
|
|
94
|
+
| `--media-upload-item-transition` | `box-shadow 0.2s ease, transform 0.2s ease` | transition | Card hover transition. |
|
|
95
|
+
| `--media-upload-item-hover-box-shadow` | `0 6px 18px rgba(0,0,0,0.14)` | box-shadow | Card shadow on hover. |
|
|
96
|
+
| `--media-upload-item-hover-transform` | `translateY(-2px)` | transform | Card transform on hover. |
|
|
97
|
+
| `--media-upload-item-object-fit` | `cover` | object-fit | Object-fit of image thumbnails. |
|
|
98
|
+
|
|
99
|
+
The loading placeholder is the `Shimmer` component sized to fill the card; theme it with the standard `--shimmer-*` variables (`--shimmer-background`, `--shimmer-highlight`, `--shimmer-duration`).
|
|
100
|
+
| `--media-upload-file-icon-color` | `#8a8f98` | color | Color of the non-image file icon. |
|
|
101
|
+
| `--media-upload-file-icon-size` | `36px` | height/width | Size of the non-image file icon. |
|
|
102
|
+
| `--media-upload-meta-padding` | `6px 8px` | padding | Padding of the name/size overlay. |
|
|
103
|
+
| `--media-upload-meta-background` | `linear-gradient(to top, rgba(0,0,0,0.72), rgba(0,0,0,0))` | background | Gradient behind the overlay on image cards. |
|
|
104
|
+
| `--media-upload-meta-color` | `#ffffff` | color | Text color of the overlay on image cards. |
|
|
105
|
+
| `--media-upload-file-meta-background` | `transparent` | background | Overlay background on file cards. |
|
|
106
|
+
| `--media-upload-file-meta-color` | `#52525b` | color | Overlay text color on file cards. |
|
|
107
|
+
| `--media-upload-meta-name-font-size` | `11px` | font-size | Font size of the file name. |
|
|
108
|
+
| `--media-upload-meta-name-font-weight` | `500` | font-weight | Weight of the file name. |
|
|
109
|
+
| `--media-upload-meta-size-font-size` | `10px` | font-size | Font size of the file size. |
|
|
110
|
+
| `--media-upload-meta-size-opacity` | `0.85` | opacity | Opacity of the file size text. |
|
|
111
|
+
| `--media-upload-remove-inset` | `6px` | top/right | Inset of the remove button from the corner. |
|
|
112
|
+
| `--media-upload-remove-padding` | `4px` | padding | Inner padding of the remove button. |
|
|
113
|
+
| `--media-upload-remove-size` | `24px` | height/width | Size of the remove button. |
|
|
114
|
+
| `--media-upload-remove-icon-size` | `100%` | height/width | Size of the icon inside the remove button. |
|
|
115
|
+
| `--media-upload-remove-border` | `none` | border | Border of the remove button. |
|
|
116
|
+
| `--media-upload-remove-border-radius` | `50%` | border-radius | Corner rounding of the remove button. |
|
|
117
|
+
| `--media-upload-remove-background-color` | `rgba(0,0,0,0.55)` | background-color | Background of the remove button. |
|
|
118
|
+
| `--media-upload-remove-color` | `#ffffff` | color | Icon color of the remove button. |
|
|
119
|
+
| `--media-upload-remove-opacity` | `0` | opacity | Resting opacity (revealed on card hover). |
|
|
120
|
+
| `--media-upload-remove-transition` | `opacity 0.18s ease, background-color 0.18s ease` | transition | Remove button transition. |
|
|
121
|
+
| `--media-upload-remove-hover-background-color` | `rgba(0,0,0,0.78)` | background-color | Remove button background on hover. |
|
|
122
|
+
| `--media-upload-remove-hover-color` | `var(--media-upload-remove-color)` | color | Remove button icon color on hover. |
|
|
123
|
+
| `--media-upload-add-gap` | `6px` | gap | Gap between drop-tile icon/text rows. |
|
|
124
|
+
| `--media-upload-add-padding` | `12px` | padding | Inner padding of the drop tile. |
|
|
125
|
+
| `--media-upload-add-background-color` | `#fafafa` | background-color | Background of the drop tile. |
|
|
126
|
+
| `--media-upload-add-border` | `1.5px dashed #c8ccd2` | border | Border of the drop tile. |
|
|
127
|
+
| `--media-upload-add-color` | `#6b7280` | color | Text/icon color of the drop tile. |
|
|
128
|
+
| `--media-upload-add-transition` | `border-color/background/color 0.18s ease` | transition | Drop tile transition. |
|
|
129
|
+
| `--media-upload-add-hover-background-color` | `#f1f5ff` | background-color | Drop tile background on hover. |
|
|
130
|
+
| `--media-upload-add-hover-border` | `1.5px dashed #6d8eff` | border | Drop tile border on hover. |
|
|
131
|
+
| `--media-upload-add-hover-color` | `#3b5bdb` | color | Drop tile color on hover. |
|
|
132
|
+
| `--media-upload-add-dragging-background-color` | `#e7efff` | background-color | Drop tile background while dragging over. |
|
|
133
|
+
| `--media-upload-add-dragging-border` | `1.5px solid #3b5bdb` | border | Drop tile border while dragging over. |
|
|
134
|
+
| `--media-upload-add-dragging-color` | `#3b5bdb` | color | Drop tile color while dragging over. |
|
|
135
|
+
| `--media-upload-add-icon-size` | `22px` | height/width | Size of the drop-tile icon. |
|
|
136
|
+
| `--media-upload-add-text-font-size` | `11px` | font-size | Font size of the drop-tile caption. |
|
|
137
|
+
| `--media-upload-add-text-line-height` | `1.3` | line-height | Line height of the drop-tile caption. |
|
|
138
|
+
| `--media-upload-add-hint-font-size` | `10px` | font-size | Font size of the drop-tile hint. |
|
|
139
|
+
| `--media-upload-add-hint-color` | `#9aa0a8` | color | Color of the drop-tile hint. |
|
|
140
|
+
| `--media-upload-error-font-size` | `12px` | font-size | Font size of the inline error. |
|
|
141
|
+
| `--media-upload-error-color` | `#e0334b` | color | Color of the inline error. |
|
|
142
|
+
| `--media-upload-error-margin` | `8px 0 0 0` | margin | Margin above the inline error. |
|
|
143
|
+
|
|
144
|
+
## Web Component
|
|
145
|
+
|
|
146
|
+
Tag: `<pui-media-upload>`
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<pui-media-upload label="Attachments" accept=".pdf,.doc,.docx" max-length="3" multiple></pui-media-upload>
|
|
150
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Resizable
|
|
2
|
+
|
|
3
|
+
A wrapper that makes its content user-resizable via drag handles on the edges/corners you choose. It keeps the rest of the library layout-agnostic: drop any content (a `Chat` panel, a `Modal`, an image, a card) inside and pick which `handles` to expose. Dragging updates the bindable `width`/`height` (clamped to min/max), so the size is observable and persistable. Each handle is a focusable WAI-ARIA splitter — arrow keys resize by `step`, with `role="separator"`, `aria-orientation`, and `aria-valuenow/min/max`.
|
|
4
|
+
|
|
5
|
+
Resize only changes size, never position — so the handle edges you pick should match how the element is anchored (a bottom-right floating panel resizes from its top-left; a left-docked panel from its right edge).
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```svelte
|
|
10
|
+
<script>
|
|
11
|
+
import { Resizable } from 'polymorph-ui-components';
|
|
12
|
+
|
|
13
|
+
let width = $state(420);
|
|
14
|
+
let height = $state(600);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<Resizable bind:width bind:height minWidth={320} maxWidth={680} handles={['right', 'bottom', 'bottom-right']}>
|
|
18
|
+
<!-- any content; give it height: 100% to fill -->
|
|
19
|
+
<Chat {messages} {onsend} />
|
|
20
|
+
</Resizable>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Props
|
|
24
|
+
|
|
25
|
+
| Prop | Type | Required | Default | Description |
|
|
26
|
+
| ----------- | -------------- | -------- | ------------------ | --------------------------------------------------------------------------- |
|
|
27
|
+
| width | `number\|null` | No | `null` | Bindable. Width in px. `null` until first resize (adopts the rendered size).|
|
|
28
|
+
| height | `number\|null` | No | `null` | Bindable. Height in px. |
|
|
29
|
+
| minWidth | `number` | No | `0` | Minimum width in px. |
|
|
30
|
+
| maxWidth | `number` | No | `Infinity` | Maximum width in px. |
|
|
31
|
+
| minHeight | `number` | No | `0` | Minimum height in px. |
|
|
32
|
+
| maxHeight | `number` | No | `Infinity` | Maximum height in px. |
|
|
33
|
+
| handles | `ResizeEdge[]` | No | `['bottom-right']` | Which handles to render: `top`, `right`, `bottom`, `left`, `top-left`, `top-right`, `bottom-left`, `bottom-right`. |
|
|
34
|
+
| step | `number` | No | `16` | Pixels per arrow-key press (keyboard resize). |
|
|
35
|
+
| disabled | `boolean` | No | `false` | Hide handles and disable resizing. |
|
|
36
|
+
| handleLabel | `string` | No | `'Resize'` | Aria-label for the handles. |
|
|
37
|
+
| children | `Snippet` | No | `-` | The content to make resizable. |
|
|
38
|
+
| testId | `string` | No | `-` | `data-pw` on the root element. |
|
|
39
|
+
| classes | `string` | No | `-` | Class string on the root element. |
|
|
40
|
+
|
|
41
|
+
## Events
|
|
42
|
+
|
|
43
|
+
| Event | Type | Description |
|
|
44
|
+
| ------------- | ------------------------------------------ | ---------------------------------------- |
|
|
45
|
+
| onresize | `(size: { width, height }) => void` | Fires continuously during a resize. |
|
|
46
|
+
| onresizestart | `(size: { width, height }) => void` | Fires when a drag/keyboard resize begins.|
|
|
47
|
+
| onresizeend | `(size: { width, height }) => void` | Fires when a drag resize ends. |
|
|
48
|
+
|
|
49
|
+
## Keyboard Interactions
|
|
50
|
+
|
|
51
|
+
Each handle is a focusable splitter. Focus one and resize with the keyboard:
|
|
52
|
+
|
|
53
|
+
| Key | Action |
|
|
54
|
+
| ---------------------------- | ------------------------------------------------------------------ |
|
|
55
|
+
| `Arrow Left` / `Arrow Right` | Adjust width by `step` px (on handles that control width). |
|
|
56
|
+
| `Arrow Up` / `Arrow Down` | Adjust height by `step` px (on handles that control height). |
|
|
57
|
+
|
|
58
|
+
All changes are clamped to `minWidth`/`maxWidth` and `minHeight`/`maxHeight`.
|
|
59
|
+
|
|
60
|
+
## Accessibility
|
|
61
|
+
|
|
62
|
+
Handles follow the WAI-ARIA **window splitter** pattern: each is `role="separator"`, focusable (`tabindex`), with `aria-orientation` and `aria-valuenow`/`aria-valuemin`/`aria-valuemax` reflecting the current/allowed size, and an `aria-label` (`handleLabel`, default `'Resize'`). Hidden entirely when `disabled`.
|
|
63
|
+
|
|
64
|
+
## Type Reference
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
type ResizeEdge = 'top' | 'right' | 'bottom' | 'left' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
68
|
+
type ResizeSize = { width: number; height: number };
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## CSS Variables
|
|
72
|
+
|
|
73
|
+
| Variable | Default | CSS Property | Description |
|
|
74
|
+
| ----------------------------------------- | -------------------- | ------------ | ---------------------------------------- |
|
|
75
|
+
| `--resizable-max-width` | `none` | max-width | Caps the rendered width (e.g. to fit a container/viewport); the bound `width` is clamped to it visually. |
|
|
76
|
+
| `--resizable-max-height` | `none` | max-height | Caps the rendered height regardless of `height`. |
|
|
77
|
+
| `--resizable-transition` | `none` | transition | Transition for programmatic size changes (e.g. an expand/collapse animation). Automatically suppressed while the user is actively drag-resizing and under `prefers-reduced-motion: reduce`. |
|
|
78
|
+
| `--resizable-edge-size` | `8px` | width/height | Hit-area thickness of edge handles. |
|
|
79
|
+
| `--resizable-corner-size` | `14px` | width/height | Hit-area size of corner handles. |
|
|
80
|
+
| `--resizable-handle-color` | `transparent` | background | Handle fill (set to make handles visible).|
|
|
81
|
+
| `--resizable-handle-z-index` | `2` | z-index | Stacking order of edge handles. |
|
|
82
|
+
| `--resizable-corner-z-index` | `3` | z-index | Stacking order of corner handles. |
|
|
83
|
+
| `--resizable-handle-focus-outline` | `2px solid #3b5bdb` | outline | Focus ring on a keyboard-focused handle. |
|
|
84
|
+
| `--resizable-handle-focus-outline-offset` | `-2px` | outline-offset | Focus ring offset. |
|
|
85
|
+
|
|
86
|
+
## Web Component
|
|
87
|
+
|
|
88
|
+
Tag: `<pui-resizable>`
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<pui-resizable width="420" height="600" min-width="320"></pui-resizable>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Set `.handles` and the resize callbacks via JavaScript.
|
package/build/docs/Tabs.md
CHANGED
|
@@ -64,7 +64,7 @@ Override these custom properties to theme the component.
|
|
|
64
64
|
|
|
65
65
|
| Variable | Default | CSS Property | Description |
|
|
66
66
|
| -------------------------------- | --------------------------------------- | ---------------- | --------------------------------------------------------- |
|
|
67
|
-
| `--tabs-bar-background` |
|
|
67
|
+
| `--tabs-bar-background` | `transparent` | background | Background color of the tab bar container (transparent so it adapts to any surface). |
|
|
68
68
|
| `--tabs-bar-padding` | `0px` | padding | Padding inside the tab bar container. |
|
|
69
69
|
| `--tabs-bar-gap` | `0px` | gap | Gap between individual tab items. |
|
|
70
70
|
| `--tabs-bar-border-bottom` | `1px solid #e4e4e7` | border-bottom | Bottom border of the tab bar container. |
|
package/build/docs/_index.json
CHANGED
|
@@ -35,6 +35,38 @@
|
|
|
35
35
|
"name": "Carousel",
|
|
36
36
|
"description": "An auto-playing slideshow that renders Svelte components as slides. Supports touch swipe and mouse drag for navigation. Shows optional dot indicators below the slides for direct navigation."
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
"name": "Chat",
|
|
40
|
+
"description": "A full chat surface composing ChatHeader, ChatMessageList, ChatSuggestions, ChatToolStatus, and ChatComposer. Fully controlled (pass `messages`, handle `onsend`) with no baked-in transport. Opt-in features: header image, stop-generation, voice mic, file attachments, prompt suggestions, smart autoscroll, and per-message copy/retry/feedback. Pair with the decoupled `ChatController` runes class — message state, streaming, typewriter reveal, retry, and session threading — which delegates the network call to a pluggable `ChatTransport` (adapt SSE, WebSocket, or polling). Markdown is not bundled — pass pre-sanitized HTML on a message's `html` field."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "ChatBubble",
|
|
44
|
+
"description": "A floating launcher button (FAB) pinned to a viewport corner that toggles a floating panel (role=dialog). Drop a Chat (or anything) inside via the children snippet — ChatBubble owns only the launcher, corner positioning, bindable `open` state, focus management (focus into panel on open, Escape to close and return focus), and reuses the Button component for the launcher. Optionally `draggable` (grab the launcher to reposition the whole widget, with click-vs-drag detection and viewport clamping; bindable `dragX`/`dragY`). `dragMode` controls drag style: `'snap'` (default) anchors to the nearest left/right screen edge on release like a mobile chat head (panel re-opens toward center), `'free'` stays where dropped. Optionally `resizable` (resize the open panel; bindable `panelWidth`/`panelHeight`, handles derived from the corner via the Resizable component). Decoupled from its contents; fully themeable via CSS variables."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "ChatComposer",
|
|
48
|
+
"description": "An auto-growing message input with a send button (the Button component). Enter submits, Shift+Enter inserts a newline (IME-safe); clears on submit. Opt-in controls light up when you wire a callback: `onattach` adds a file picker with removable attachment chips (bindable `attachments`), `onvoice` adds a mic button (with `recording` state), and `streaming` + `onstop` morph send into a stop button. Every icon is snippet-overridable."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "ChatHeader",
|
|
52
|
+
"description": "A header bar for a chat surface: an optional brand image (via the Img component) or avatar snippet, title and subtitle, extra actions snippet, and a close button (the Button component) shown when `onclose` is provided. Close icon falls back to a built-in asset and is overridable via snippet."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "ChatMessage",
|
|
56
|
+
"description": "A single chat bubble. The primitive is the two-party `role`: `sender` (right, accent bubble) or `responder` (left). `user`/`assistant`/`system` and any custom string are recognized extensions that map onto a party (sender/user → sender; everything else → responder), so LLM message arrays drop in unchanged; the exported `partyOf(role)` resolves a role to its party. Renders pre-sanitized `html` (e.g. rendered markdown) or plain `content`, shows a typing indicator (LoadingDots) while streaming with no content, and accepts avatar, header, and attachments snippets. Opt-in hover actions on responder messages: built-in copy (with checkmark feedback), retry (onretry), and 👍/👎 (onfeedback). Basic markdown elements are styled via :global."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "ChatMessageList",
|
|
60
|
+
"description": "A scrollable conversation container with smart auto-scroll: it sticks to the bottom only while you're already near it, and shows a jump-to-latest button when you've scrolled up. Renders each message with ChatMessage by default or a custom `message` snippet, shows an `empty` snippet when there are no messages, and forwards opt-in message actions (allowCopy, onretry, onfeedback). Uses a Svelte action (no effects), respecting reduced-motion."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "ChatSuggestions",
|
|
64
|
+
"description": "A row of tappable prompt chips (the Pill component), typically shown on an empty conversation. Each item is a string or `{ label, value }`; selecting a chip fires `onselect` with the value and index."
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "ChatToolStatus",
|
|
68
|
+
"description": "A compact status pill pairing a spinner (the Loader component) with a label to show what the assistant is doing (searching, calling a tool, thinking). The leading indicator is overridable via snippet."
|
|
69
|
+
},
|
|
38
70
|
{
|
|
39
71
|
"name": "Checkbox",
|
|
40
72
|
"description": "A styled checkbox input with a custom SVG checkmark. Supports checked state binding, disabled state, and configurable size and colors via CSS variables."
|
|
@@ -63,6 +95,10 @@
|
|
|
63
95
|
"name": "ContextMenu",
|
|
64
96
|
"description": "A right-click context menu with a flat list of items supporting separators, disabled items, danger styling, optional icons, and shortcut labels. Has keyboard navigation, positions itself at the click point, and adjusts to stay within the viewport."
|
|
65
97
|
},
|
|
98
|
+
{
|
|
99
|
+
"name": "Draggable",
|
|
100
|
+
"description": "A wrapper that lets the user drag its content to reposition it via `transform: translate(x, y)` (never affecting flow). Bindable `x`/`y` make the position observable/persistable; supports a `handle` selector, single-`axis` constraint, viewport `bounds`, and keyboard arrow-key movement by `step`, plus drag events. Layout-agnostic — layers on top of the element's existing positioning. Pair with a `fixed` element for a draggable floating panel."
|
|
101
|
+
},
|
|
66
102
|
{
|
|
67
103
|
"name": "Gauge",
|
|
68
104
|
"description": "A full-circle ring gauge that displays a `value` clamped to 0-100 as a single SVG arc. Has an animated stroke-dashoffset transition and an optional centered percentage label. Uses SVG stroke-dasharray for the arc rendering."
|
|
@@ -107,6 +143,14 @@
|
|
|
107
143
|
"name": "LoadingDots",
|
|
108
144
|
"description": "Animated dot sequence for inline loading indication. Renders a configurable number of dots (default 3) that animate in a staggered sequence using either a bounce or pulse animation. Size and duration are controlled via CSS variables."
|
|
109
145
|
},
|
|
146
|
+
{
|
|
147
|
+
"name": "MediaPlayer",
|
|
148
|
+
"description": "An image or video player with a hover-revealed control overlay. For videos it shows a centered play/pause control and a bottom-aligned mute/unmute control, with built-in icons (imported from assets) that can be replaced via snippet props. The `playing` and `muted` states are bindable, and click/keyboard toggling is wired up. Control buttons reuse the Button component. Unstyled by default — sizing, overlay color, and control appearance are driven by CSS variables. Set `controls` to use the browser's native video controls instead."
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "MediaUpload",
|
|
152
|
+
"description": "A polished file upload field with a drag-and-drop drop zone, image thumbnail previews, and file cards (icon + name + size) for non-image files. Validates dropped/selected files against `accept` and `maxFileSize`, enforces a `maxLength` cap, and surfaces an inline error with customizable messages. Shows a label, attached/limit counter, helper description, and per-card hover remove buttons that reuse the Button component. Exposes the bindable `files` array plus `onchange`, `onremove`, and `onerror` callbacks. Built-in icons (imported from assets) are replaceable via snippet props, and every dimension, color, border, and state is themeable through CSS variables."
|
|
153
|
+
},
|
|
110
154
|
{
|
|
111
155
|
"name": "Menu",
|
|
112
156
|
"description": "A dropdown action menu with full keyboard navigation (ArrowUp/Down, Enter/Space, Escape, Home/End), typeahead search, click-outside dismiss, separator lines, danger-styled items, disabled items, optional icons, and configurable position. Focus is managed automatically."
|
|
@@ -147,6 +191,10 @@
|
|
|
147
191
|
"name": "RelativeTime",
|
|
148
192
|
"description": "Displays a human-readable relative time string (e.g., '5 minutes ago') that auto-updates at a configurable interval. Uses Intl.RelativeTimeFormat for locale-aware formatting. Renders a semantic <time> element. Optionally wraps in a Tooltip showing the full date."
|
|
149
193
|
},
|
|
194
|
+
{
|
|
195
|
+
"name": "Resizable",
|
|
196
|
+
"description": "A wrapper that makes its content user-resizable via drag handles on chosen edges/corners (`handles`). Dragging updates the bindable `width`/`height` (clamped to min/max) so size is observable and persistable; `onresize`/`onresizestart`/`onresizeend` fire too. Each handle is a focusable WAI-ARIA splitter — arrow keys resize by `step`, with role=separator and aria-valuenow/min/max. Resize changes size only (not position), so pick handle edges that match how the element is anchored. Layout-agnostic: wrap a Chat panel, Modal, image, or card."
|
|
197
|
+
},
|
|
150
198
|
{
|
|
151
199
|
"name": "Scroller",
|
|
152
200
|
"description": "Overflowing horizontal or vertical item list with scroll controls. Shows navigation arrows when content overflows, with gradient fade edges. Supports drag-to-scroll, snap-to-item, touch device detection, and scroll position tracking."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polymorph-ui-components-mcp",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for polymorph-ui-components - provides structured access to component props, CSS variables, and usage patterns",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|