intelliwaketssveltekitv25 1.0.82 → 1.0.84
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 +2 -2
- package/dist/DropDownControl.svelte +1 -0
- package/dist/app.css +1 -1
- package/docs/DateRangePicker.md +272 -0
- package/docs/DisplayHTML.md +249 -0
- package/docs/DropDown.md +269 -0
- package/docs/Functions.md +796 -0
- package/docs/Home.md +87 -0
- package/docs/Icon.md +203 -0
- package/docs/Importer.md +328 -0
- package/docs/ImporterAnalysis.md +249 -0
- package/docs/ImporterLoad.md +288 -0
- package/docs/InputNumber.md +159 -0
- package/docs/Integration.md +215 -0
- package/docs/Modal.md +207 -0
- package/docs/MultiSelect.md +304 -0
- package/docs/Paginator.md +332 -0
- package/docs/Search.md +364 -0
- package/docs/SlideDown.md +358 -0
- package/docs/Svelte-5-Patterns.md +364 -0
- package/docs/Switch.md +107 -0
- package/docs/TabHeader.md +333 -0
- package/docs/TabHref.md +370 -0
- package/docs/TextArea.md +118 -0
- package/docs/_Sidebar.md +38 -0
- package/llms.txt +113 -0
- package/package.json +8 -7
- package/llm.txt +0 -1635
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# DisplayHTML Component
|
|
2
|
+
|
|
3
|
+
**Purpose:** Safely render text, HTML, or Svelte snippets with automatic URL link conversion
|
|
4
|
+
|
|
5
|
+
**When to Use:**
|
|
6
|
+
- Display user-generated content that may contain HTML
|
|
7
|
+
- Automatically convert URLs to clickable links
|
|
8
|
+
- Render dynamic content from database fields
|
|
9
|
+
- Display formatted text with HTML tags
|
|
10
|
+
- Conditionally render Svelte snippets
|
|
11
|
+
|
|
12
|
+
## Key Props
|
|
13
|
+
|
|
14
|
+
- `value: string | null | undefined | Snippet` (required) - Content to display
|
|
15
|
+
- `anchorClasses?: string` (default: '') - CSS classes for auto-generated anchor links
|
|
16
|
+
- `noLinkReplace?: boolean` (default: false) - Disable automatic URL-to-link conversion
|
|
17
|
+
- `hidden?: boolean` - Hide the component
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
### Automatic Link Conversion
|
|
22
|
+
By default, the component automatically converts plain URLs in text to clickable anchor links:
|
|
23
|
+
```
|
|
24
|
+
"Visit https://example.com" → "Visit <a href="https://example.com">https://example.com</a>"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### HTML Detection
|
|
28
|
+
The component intelligently detects HTML content and renders it using `{@html}` when needed, while rendering plain text normally.
|
|
29
|
+
|
|
30
|
+
### Snippet Support
|
|
31
|
+
Pass Svelte snippets as the `value` for dynamic component rendering.
|
|
32
|
+
|
|
33
|
+
### Text-to-HTML Conversion
|
|
34
|
+
Converts newlines to `<br>` tags for proper text formatting.
|
|
35
|
+
|
|
36
|
+
## Usage Examples
|
|
37
|
+
|
|
38
|
+
```svelte
|
|
39
|
+
<script>
|
|
40
|
+
import { DisplayHTML } from 'intelliwaketssveltekitv25';
|
|
41
|
+
|
|
42
|
+
let plainText = 'Hello, world!';
|
|
43
|
+
let htmlContent = '<strong>Bold text</strong> and <em>italic text</em>';
|
|
44
|
+
let textWithUrl = 'Visit our site at https://example.com for more info';
|
|
45
|
+
let multilineText = 'Line 1\nLine 2\nLine 3';
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<!-- Plain text -->
|
|
49
|
+
<DisplayHTML value={plainText} />
|
|
50
|
+
<!-- Output: Hello, world! -->
|
|
51
|
+
|
|
52
|
+
<!-- HTML content -->
|
|
53
|
+
<DisplayHTML value={htmlContent} />
|
|
54
|
+
<!-- Output: Bold text and italic text (rendered) -->
|
|
55
|
+
|
|
56
|
+
<!-- Text with URL (auto-converted to link) -->
|
|
57
|
+
<DisplayHTML value={textWithUrl} />
|
|
58
|
+
<!-- Output: Visit our site at <a href="https://example.com">https://example.com</a> for more info -->
|
|
59
|
+
|
|
60
|
+
<!-- Disable link conversion -->
|
|
61
|
+
<DisplayHTML value={textWithUrl} noLinkReplace />
|
|
62
|
+
<!-- Output: Visit our site at https://example.com for more info (plain text) -->
|
|
63
|
+
|
|
64
|
+
<!-- Styled links -->
|
|
65
|
+
<DisplayHTML
|
|
66
|
+
value={textWithUrl}
|
|
67
|
+
anchorClasses="text-blue-600 hover:underline"
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<!-- Conditional display -->
|
|
71
|
+
<DisplayHTML value={description} hidden={!showDescription} />
|
|
72
|
+
|
|
73
|
+
<!-- With Svelte snippet -->
|
|
74
|
+
<DisplayHTML value={mySnippet} />
|
|
75
|
+
|
|
76
|
+
<!-- Null-safe (won't render if null/undefined) -->
|
|
77
|
+
<DisplayHTML value={maybeNull} />
|
|
78
|
+
|
|
79
|
+
<!-- Multiline text (newlines converted to <br>) -->
|
|
80
|
+
<DisplayHTML value={multilineText} />
|
|
81
|
+
<!-- Output:
|
|
82
|
+
Line 1<br>
|
|
83
|
+
Line 2<br>
|
|
84
|
+
Line 3
|
|
85
|
+
-->
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Real-World Examples
|
|
89
|
+
|
|
90
|
+
### User Comments
|
|
91
|
+
```svelte
|
|
92
|
+
<script>
|
|
93
|
+
let comment = $state('Check out https://example.com - it's great!');
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<DisplayHTML
|
|
97
|
+
value={comment}
|
|
98
|
+
anchorClasses="text-blue-500 hover:underline"
|
|
99
|
+
/>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Product Description
|
|
103
|
+
```svelte
|
|
104
|
+
<script>
|
|
105
|
+
export let data;
|
|
106
|
+
let product = data.product;
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<h2>{product.name}</h2>
|
|
110
|
+
<DisplayHTML value={product.descriptionHTML} />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Dynamic Content from Database
|
|
114
|
+
```svelte
|
|
115
|
+
<script>
|
|
116
|
+
// Database field may contain HTML or plain text
|
|
117
|
+
let content = $state(data.content); // Could be "<p>HTML</p>" or "Plain text"
|
|
118
|
+
</script>
|
|
119
|
+
|
|
120
|
+
<DisplayHTML value={content} />
|
|
121
|
+
<!-- Automatically handles both cases -->
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Email Body Display
|
|
125
|
+
```svelte
|
|
126
|
+
<script>
|
|
127
|
+
let emailBody = $state(email.body);
|
|
128
|
+
</script>
|
|
129
|
+
|
|
130
|
+
<div class="email-content">
|
|
131
|
+
<DisplayHTML
|
|
132
|
+
value={emailBody}
|
|
133
|
+
anchorClasses="text-blue-600 underline"
|
|
134
|
+
/>
|
|
135
|
+
</div>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Conditional Rendering with Snippets
|
|
139
|
+
```svelte
|
|
140
|
+
<script>
|
|
141
|
+
let useCustomRender = $state(true);
|
|
142
|
+
</script>
|
|
143
|
+
|
|
144
|
+
{#snippet customContent()}
|
|
145
|
+
<div class="custom">
|
|
146
|
+
Custom rendered content
|
|
147
|
+
</div>
|
|
148
|
+
{/snippet}
|
|
149
|
+
|
|
150
|
+
<DisplayHTML value={useCustomRender ? customContent : 'Plain text'} />
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Security Considerations
|
|
154
|
+
|
|
155
|
+
**Important:** This component uses `{@html}` to render HTML content. Only use it with **trusted content**. Never pass unsanitized user input directly without server-side sanitization.
|
|
156
|
+
|
|
157
|
+
### Safe Usage
|
|
158
|
+
```svelte
|
|
159
|
+
<!-- ✅ SAFE: Content from your database (sanitized on server) -->
|
|
160
|
+
<DisplayHTML value={product.description} />
|
|
161
|
+
|
|
162
|
+
<!-- ✅ SAFE: Static content you control -->
|
|
163
|
+
<DisplayHTML value="<strong>Our Policy</strong>" />
|
|
164
|
+
|
|
165
|
+
<!-- ❌ UNSAFE: Raw user input without sanitization -->
|
|
166
|
+
<DisplayHTML value={userInput} />
|
|
167
|
+
<!-- Should be: -->
|
|
168
|
+
<DisplayHTML value={sanitizedUserInput} />
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Sanitization Example (Server-side)
|
|
172
|
+
```typescript
|
|
173
|
+
// +page.server.ts
|
|
174
|
+
import DOMPurify from 'isomorphic-dompurify';
|
|
175
|
+
|
|
176
|
+
export const load = async () => {
|
|
177
|
+
const rawContent = await db.content.get();
|
|
178
|
+
const sanitizedContent = DOMPurify.sanitize(rawContent);
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
content: sanitizedContent
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Common Patterns
|
|
187
|
+
|
|
188
|
+
### Table Cell with Links
|
|
189
|
+
```svelte
|
|
190
|
+
<ArrayTable data={items} columns={[
|
|
191
|
+
{
|
|
192
|
+
title: 'Description',
|
|
193
|
+
cell: (item) => ({ snippet: () => (
|
|
194
|
+
<DisplayHTML
|
|
195
|
+
value={item.description}
|
|
196
|
+
anchorClasses="text-primary-main"
|
|
197
|
+
/>
|
|
198
|
+
)})
|
|
199
|
+
}
|
|
200
|
+
]} />
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Fallback Content
|
|
204
|
+
```svelte
|
|
205
|
+
<DisplayHTML value={content || 'No description available'} />
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Optional Display
|
|
209
|
+
```svelte
|
|
210
|
+
{#if showDetails}
|
|
211
|
+
<DisplayHTML value={details} />
|
|
212
|
+
{/if}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Common Mistakes
|
|
216
|
+
|
|
217
|
+
- ❌ Passing raw user input without sanitization (XSS risk)
|
|
218
|
+
✅ Correct: Sanitize HTML content on the server before rendering
|
|
219
|
+
|
|
220
|
+
- ❌ Not using `noLinkReplace` when you don't want URL conversion
|
|
221
|
+
✅ Correct: Set `noLinkReplace={true}` for technical content with URLs
|
|
222
|
+
|
|
223
|
+
- ❌ Using this component when simple text rendering would suffice
|
|
224
|
+
✅ Correct: Use plain `{value}` for simple text, DisplayHTML only when needed
|
|
225
|
+
|
|
226
|
+
- ❌ Forgetting that `null` or `undefined` values won't render
|
|
227
|
+
✅ Correct: Provide fallback: `value={content || 'Default text'}`
|
|
228
|
+
|
|
229
|
+
## Related Functions
|
|
230
|
+
|
|
231
|
+
The component uses these utility functions from `@solidbasisventures/intelliwaketsfoundation`:
|
|
232
|
+
- **ReplaceLinks(html, classes)** - Converts URLs to anchor tags
|
|
233
|
+
- **TextToHTML(text)** - Converts plain text to HTML (newlines to `<br>`)
|
|
234
|
+
- **IncludesHTML(text)** - Detects if string contains HTML tags
|
|
235
|
+
|
|
236
|
+
## Props Reference
|
|
237
|
+
|
|
238
|
+
| Prop | Type | Default | Description |
|
|
239
|
+
|------|------|---------|-------------|
|
|
240
|
+
| `value` | `string \| null \| undefined \| Snippet` | (required) | Content to display |
|
|
241
|
+
| `anchorClasses` | `string` | `''` | CSS classes for auto-generated links |
|
|
242
|
+
| `noLinkReplace` | `boolean` | `false` | Skip URL-to-link conversion |
|
|
243
|
+
| `hidden` | `boolean` | `false` | Hide component |
|
|
244
|
+
|
|
245
|
+
## Performance Notes
|
|
246
|
+
|
|
247
|
+
- The component efficiently detects HTML vs plain text to minimize unnecessary `{@html}` usage
|
|
248
|
+
- Link replacement only occurs when `noLinkReplace` is false
|
|
249
|
+
- Snippet detection happens once via `$derived`
|
package/docs/DropDown.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# DropDown Component
|
|
2
|
+
|
|
3
|
+
**Replaces:** `<select>` elements and custom dropdown menus
|
|
4
|
+
|
|
5
|
+
**Purpose:** Rich dropdown menu with keyboard navigation, icons, search, and action handling
|
|
6
|
+
|
|
7
|
+
**When to Use:**
|
|
8
|
+
- Action menus (context menus, toolbar dropdowns)
|
|
9
|
+
- Navigation dropdowns with links
|
|
10
|
+
- Replacing `<select>` when you need icons, dividers, or complex items
|
|
11
|
+
- Any menu that needs better UX than native `<select>`
|
|
12
|
+
|
|
13
|
+
## Key Props
|
|
14
|
+
|
|
15
|
+
- `show?: boolean` ($bindable) - Control dropdown open/closed state
|
|
16
|
+
- `position?: TDropDownControlPosition` (default: null) - Menu position relative to button
|
|
17
|
+
- `ddActions?: IDDAction[]` (default: []) - Array of menu items/actions (see IDDAction interface below)
|
|
18
|
+
- `noCaret?: boolean` - Hide the dropdown arrow icon
|
|
19
|
+
- `buttonTitle?: string | null` - Button text (if not using `button` snippet)
|
|
20
|
+
- `buttonClass?: string` - CSS classes for the button
|
|
21
|
+
- `controlClass?: string` - CSS classes for the dropdown wrapper
|
|
22
|
+
- `toggleClass?: string` - CSS classes for the toggle container
|
|
23
|
+
- `inputControl?: boolean` - Style button as input control
|
|
24
|
+
- `fullBlock?: boolean` - Make button full width
|
|
25
|
+
- `bodyClass?: string` - CSS classes for dropdown body/menu
|
|
26
|
+
- `sameSize?: boolean` - Make dropdown menu same width as button
|
|
27
|
+
- `zIndex?: number` (default: 40) - Z-index for dropdown positioning
|
|
28
|
+
- `disabled?: boolean` - Disable the dropdown
|
|
29
|
+
- `hidden?: boolean` - Hide the dropdown
|
|
30
|
+
- `hideEmptyDDActions?: boolean` - Auto-hide if no actions provided
|
|
31
|
+
- `verbose?: boolean` - Enable console logging for debugging
|
|
32
|
+
- `dataColor?: TDefaultColorPalate` - Color theme for button
|
|
33
|
+
- `clientWidth?: number` ($bindable) - Width of the button element
|
|
34
|
+
|
|
35
|
+
## Snippets
|
|
36
|
+
|
|
37
|
+
- `button?: Snippet` - Custom button content (overrides `buttonTitle`)
|
|
38
|
+
- `actions?: Snippet` - Custom menu content (in addition to or instead of `ddActions`)
|
|
39
|
+
|
|
40
|
+
## IDDAction Interface
|
|
41
|
+
|
|
42
|
+
Menu items configuration:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
interface IDDAction {
|
|
46
|
+
title?: string // Display text
|
|
47
|
+
key?: string | number // Unique key for item
|
|
48
|
+
divider?: boolean // Render as divider line
|
|
49
|
+
header?: boolean // Render as header text (bold, no click)
|
|
50
|
+
dividerGroup?: string // Auto-add divider when group changes
|
|
51
|
+
headerGroup?: string // Auto-add header when group changes
|
|
52
|
+
active?: boolean // Highlight as active/selected
|
|
53
|
+
disabled?: boolean // Disable interaction
|
|
54
|
+
hidden?: boolean // Hide from menu
|
|
55
|
+
indented?: boolean // Indent item (for hierarchy)
|
|
56
|
+
|
|
57
|
+
// Actions
|
|
58
|
+
action?: () => void // Click handler
|
|
59
|
+
href?: string // Navigation URL
|
|
60
|
+
hrefReplace?: boolean // Use replaceState navigation
|
|
61
|
+
hrefDownload?: string // Download URL
|
|
62
|
+
hrefDownloadFilename?: string // Filename for download
|
|
63
|
+
|
|
64
|
+
// Visual
|
|
65
|
+
faProps?: IFAProps // FontAwesome icon
|
|
66
|
+
imageHref?: string // Image URL for icon
|
|
67
|
+
|
|
68
|
+
// Alternate action (right side button)
|
|
69
|
+
alternateAction?: () => void // Right-side button action
|
|
70
|
+
alternateTitle?: string // Right-side button text
|
|
71
|
+
alternateFAProps?: IFAProps // Right-side button icon
|
|
72
|
+
alternateNoClose?: boolean // Keep menu open after alternate action
|
|
73
|
+
|
|
74
|
+
// Behavior
|
|
75
|
+
noCloseMenu?: boolean // Keep menu open after action
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Keyboard Navigation
|
|
80
|
+
|
|
81
|
+
- **Arrow Down:** Open menu / Move to next item
|
|
82
|
+
- **Arrow Up:** Move to previous item
|
|
83
|
+
- **Enter:** Execute selected item action
|
|
84
|
+
- **Tab:** Close menu
|
|
85
|
+
- **Type letter:** Jump to first item starting with that letter
|
|
86
|
+
|
|
87
|
+
## Usage Examples
|
|
88
|
+
|
|
89
|
+
```svelte
|
|
90
|
+
<script>
|
|
91
|
+
import { DropDown } from 'intelliwaketssveltekitv25';
|
|
92
|
+
import { faEdit, faTrash, faCopy } from '@fortawesome/free-solid-svg-icons';
|
|
93
|
+
|
|
94
|
+
let showMenu = $state(false);
|
|
95
|
+
let selectedOption = $state('option1');
|
|
96
|
+
|
|
97
|
+
const actions = [
|
|
98
|
+
{
|
|
99
|
+
title: 'Edit',
|
|
100
|
+
faProps: { icon: faEdit },
|
|
101
|
+
action: () => editItem()
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
title: 'Duplicate',
|
|
105
|
+
faProps: { icon: faCopy },
|
|
106
|
+
action: () => duplicateItem()
|
|
107
|
+
},
|
|
108
|
+
{ divider: true },
|
|
109
|
+
{
|
|
110
|
+
title: 'Delete',
|
|
111
|
+
faProps: { icon: faTrash },
|
|
112
|
+
action: () => deleteItem()
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
<!-- Simple action menu -->
|
|
118
|
+
<DropDown
|
|
119
|
+
bind:show={showMenu}
|
|
120
|
+
buttonTitle="Actions"
|
|
121
|
+
ddActions={actions}
|
|
122
|
+
/>
|
|
123
|
+
|
|
124
|
+
<!-- As select replacement with active indicator -->
|
|
125
|
+
<DropDown
|
|
126
|
+
bind:show={showOptions}
|
|
127
|
+
buttonTitle={selectedOption}
|
|
128
|
+
ddActions={[
|
|
129
|
+
{
|
|
130
|
+
title: 'Option 1',
|
|
131
|
+
active: selectedOption === 'option1',
|
|
132
|
+
action: () => selectedOption = 'option1'
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
title: 'Option 2',
|
|
136
|
+
active: selectedOption === 'option2',
|
|
137
|
+
action: () => selectedOption = 'option2'
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
title: 'Option 3',
|
|
141
|
+
active: selectedOption === 'option3',
|
|
142
|
+
action: () => selectedOption = 'option3'
|
|
143
|
+
}
|
|
144
|
+
]}
|
|
145
|
+
inputControl
|
|
146
|
+
/>
|
|
147
|
+
|
|
148
|
+
<!-- With navigation links -->
|
|
149
|
+
<DropDown
|
|
150
|
+
buttonTitle="Navigate"
|
|
151
|
+
ddActions={[
|
|
152
|
+
{ title: 'Dashboard', href: '/dashboard' },
|
|
153
|
+
{ title: 'Settings', href: '/settings' },
|
|
154
|
+
{ divider: true },
|
|
155
|
+
{ title: 'Logout', href: '/logout', hrefReplace: true }
|
|
156
|
+
]}
|
|
157
|
+
/>
|
|
158
|
+
|
|
159
|
+
<!-- With grouped items -->
|
|
160
|
+
<DropDown
|
|
161
|
+
buttonTitle="Options"
|
|
162
|
+
ddActions={[
|
|
163
|
+
{ title: 'File Operations', header: true },
|
|
164
|
+
{ title: 'Open', action: () => open() },
|
|
165
|
+
{ title: 'Save', action: () => save() },
|
|
166
|
+
{ divider: true },
|
|
167
|
+
{ title: 'Edit Operations', header: true },
|
|
168
|
+
{ title: 'Cut', action: () => cut() },
|
|
169
|
+
{ title: 'Copy', action: () => copy() },
|
|
170
|
+
{ title: 'Paste', action: () => paste() }
|
|
171
|
+
]}
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
<!-- With auto-grouping by headerGroup -->
|
|
175
|
+
<DropDown
|
|
176
|
+
buttonTitle="Grouped"
|
|
177
|
+
ddActions={[
|
|
178
|
+
{ title: 'Item 1', headerGroup: 'Group A', action: () => {} },
|
|
179
|
+
{ title: 'Item 2', headerGroup: 'Group A', action: () => {} },
|
|
180
|
+
{ title: 'Item 3', headerGroup: 'Group B', action: () => {} },
|
|
181
|
+
{ title: 'Item 4', headerGroup: 'Group B', action: () => {} }
|
|
182
|
+
]}
|
|
183
|
+
/>
|
|
184
|
+
<!-- Automatically adds headers "Group A" and "Group B" -->
|
|
185
|
+
|
|
186
|
+
<!-- Custom button content -->
|
|
187
|
+
<DropDown bind:show={showCustom} ddActions={actions}>
|
|
188
|
+
{#snippet button()}
|
|
189
|
+
<Icon icon={faEllipsisV} />
|
|
190
|
+
More Options
|
|
191
|
+
{/snippet}
|
|
192
|
+
</DropDown>
|
|
193
|
+
|
|
194
|
+
<!-- Full width dropdown -->
|
|
195
|
+
<DropDown
|
|
196
|
+
buttonTitle="Select Option"
|
|
197
|
+
ddActions={options}
|
|
198
|
+
fullBlock
|
|
199
|
+
sameSize
|
|
200
|
+
inputControl
|
|
201
|
+
/>
|
|
202
|
+
|
|
203
|
+
<!-- With disabled items -->
|
|
204
|
+
<DropDown
|
|
205
|
+
buttonTitle="Actions"
|
|
206
|
+
ddActions={[
|
|
207
|
+
{ title: 'Available Action', action: () => {} },
|
|
208
|
+
{ title: 'Coming Soon', disabled: true },
|
|
209
|
+
{ title: 'Premium Only', disabled: true }
|
|
210
|
+
]}
|
|
211
|
+
/>
|
|
212
|
+
|
|
213
|
+
<!-- With alternate actions (two buttons per row) -->
|
|
214
|
+
<DropDown
|
|
215
|
+
buttonTitle="Files"
|
|
216
|
+
ddActions={[
|
|
217
|
+
{
|
|
218
|
+
title: 'document.pdf',
|
|
219
|
+
action: () => openFile('document.pdf'),
|
|
220
|
+
alternateAction: () => downloadFile('document.pdf'),
|
|
221
|
+
alternateFAProps: { icon: faDownload }
|
|
222
|
+
}
|
|
223
|
+
]}
|
|
224
|
+
/>
|
|
225
|
+
|
|
226
|
+
<!-- Download action -->
|
|
227
|
+
<DropDown
|
|
228
|
+
buttonTitle="Export"
|
|
229
|
+
ddActions={[
|
|
230
|
+
{
|
|
231
|
+
title: 'Export as CSV',
|
|
232
|
+
hrefDownload: '/api/export?format=csv',
|
|
233
|
+
hrefDownloadFilename: 'data.csv'
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
title: 'Export as PDF',
|
|
237
|
+
hrefDownload: '/api/export?format=pdf',
|
|
238
|
+
hrefDownloadFilename: 'data.pdf'
|
|
239
|
+
}
|
|
240
|
+
]}
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Common Mistakes
|
|
245
|
+
|
|
246
|
+
- ❌ Not providing `action`, `href`, or `hrefDownload` for menu items
|
|
247
|
+
✅ Correct: Every menu item (except dividers/headers) needs an action
|
|
248
|
+
|
|
249
|
+
- ❌ Using DropDown when MultiSelect is more appropriate
|
|
250
|
+
✅ Correct: Use `MultiSelect` for selecting multiple options, `DropDown` for single actions/selections
|
|
251
|
+
|
|
252
|
+
- ❌ Forgetting to handle menu close in custom `noCloseMenu` actions
|
|
253
|
+
✅ Correct: Manually set `show = false` when using `noCloseMenu: true`
|
|
254
|
+
|
|
255
|
+
- ❌ Not using `bind:show` for controlled dropdowns
|
|
256
|
+
✅ Correct: `<DropDown bind:show={showMenu}>` to control open/close state
|
|
257
|
+
|
|
258
|
+
- ❌ Using complex objects as `key` without providing unique string/number keys
|
|
259
|
+
✅ Correct: Always provide `key` prop for array items
|
|
260
|
+
|
|
261
|
+
## Related Components
|
|
262
|
+
|
|
263
|
+
- `DropDownControl` - Lower-level dropdown control (used internally by DropDown)
|
|
264
|
+
- `MultiSelect` - For selecting multiple options from a list
|
|
265
|
+
- `Importer` - Specialized dropdown for file imports
|
|
266
|
+
|
|
267
|
+
## Storybook
|
|
268
|
+
|
|
269
|
+
See `Components/DropDown` stories
|