@iress-oss/ids-mcp-server 0.0.1-dev.5 → 0.0.1-dev.7

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 (36) hide show
  1. package/dist/componentHandlers.js +241 -0
  2. package/dist/componentHandlers.test.js +380 -0
  3. package/dist/config.js +16 -0
  4. package/dist/index.js +53 -0
  5. package/dist/iressHandlers.js +144 -0
  6. package/dist/iressHandlers.test.js +316 -0
  7. package/dist/resourceHandlers.js +67 -0
  8. package/dist/resourceHandlers.test.js +352 -0
  9. package/dist/searchHandlers.js +287 -0
  10. package/dist/searchHandlers.test.js +524 -0
  11. package/dist/toolHandler.js +31 -0
  12. package/dist/toolHandler.test.js +369 -0
  13. package/dist/tools.js +165 -0
  14. package/dist/types.js +4 -0
  15. package/dist/utils.js +59 -0
  16. package/dist/utils.test.js +286 -0
  17. package/generated/docs/components-autocomplete-docs.md +47 -3
  18. package/generated/docs/components-checkboxgroup-docs.md +17 -17
  19. package/generated/docs/components-col-docs.md +1 -1
  20. package/generated/docs/components-combobox-docs.md +4 -4
  21. package/generated/docs/components-filter-docs.md +3 -3
  22. package/generated/docs/components-form-docs.md +7 -40
  23. package/generated/docs/components-icon-docs.md +4 -4
  24. package/generated/docs/components-inputcurrency-docs.md +4 -47
  25. package/generated/docs/components-radiogroup-docs.md +21 -21
  26. package/generated/docs/components-richselect-docs.md +322 -1
  27. package/generated/docs/components-row-docs.md +4 -4
  28. package/generated/docs/components-skiplink-docs.md +1 -1
  29. package/generated/docs/components-table-ag-grid-docs.md +104 -1696
  30. package/generated/docs/components-table-docs.md +6 -6
  31. package/generated/docs/components-tabset-docs.md +28 -0
  32. package/generated/docs/extensions-editor-docs.md +12 -6
  33. package/generated/docs/introduction-docs.md +1 -1
  34. package/generated/docs/patterns-loading-docs.md +2 -2
  35. package/generated/docs/themes-available-themes-docs.md +29 -29
  36. package/package.json +14 -5
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Tests for utility functions
3
+ */
4
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5
+ import * as fs from 'fs';
6
+ import { getMarkdownFiles, mapIressComponentToFile, extractIressComponents, readFileContent, fileExists, } from './utils.js';
7
+ // Mock fs module
8
+ vi.mock('fs');
9
+ vi.mock('./config.js', () => ({
10
+ DOCS_DIR: '/mock/docs/dir',
11
+ }));
12
+ const mockedFs = vi.mocked(fs);
13
+ // Test helper functions and types
14
+ const createComponentMapping = (componentName, filePath) => ({
15
+ componentName,
16
+ filePath,
17
+ });
18
+ const mockFileList = [
19
+ 'components-button-docs.md',
20
+ 'components-input-docs.md',
21
+ 'components-card-docs.md',
22
+ ];
23
+ // Type for fs.readdirSync return value to avoid repetitive eslint-disable comments
24
+ const createMockFileArray = (...files) => files.filter((file) => file != null);
25
+ describe('utils', () => {
26
+ beforeEach(() => {
27
+ vi.clearAllMocks();
28
+ });
29
+ afterEach(() => {
30
+ vi.restoreAllMocks();
31
+ });
32
+ describe('getMarkdownFiles', () => {
33
+ it('should return empty array when docs directory does not exist', () => {
34
+ mockedFs.existsSync.mockReturnValue(false);
35
+ const result = getMarkdownFiles();
36
+ expect(result).toEqual([]);
37
+ expect(fs.existsSync).toHaveBeenCalledWith('/mock/docs/dir');
38
+ });
39
+ it('should return markdown files when directory exists', () => {
40
+ mockedFs.existsSync.mockReturnValue(true);
41
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-docs.md', 'components-input-docs.md', 'other-file.txt', 'nested/components-card-docs.md', Buffer.from('buffer-file')));
42
+ const result = getMarkdownFiles();
43
+ expect(result).toEqual([
44
+ 'components-button-docs.md',
45
+ 'components-input-docs.md',
46
+ 'nested/components-card-docs.md',
47
+ ]);
48
+ expect(fs.readdirSync).toHaveBeenCalledWith('/mock/docs/dir', {
49
+ recursive: true,
50
+ });
51
+ });
52
+ it('should handle errors gracefully', () => {
53
+ mockedFs.existsSync.mockReturnValue(true);
54
+ mockedFs.readdirSync.mockImplementation(() => {
55
+ throw new Error('Read error');
56
+ });
57
+ const consoleSpy = vi
58
+ .spyOn(console, 'error')
59
+ .mockImplementation(() => { });
60
+ const result = getMarkdownFiles();
61
+ expect(result).toEqual([]);
62
+ expect(consoleSpy).toHaveBeenCalledWith('Error reading docs directory:', expect.any(Error));
63
+ });
64
+ it('should filter out non-string entries from directory listing', () => {
65
+ mockedFs.existsSync.mockReturnValue(true);
66
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('file1.md', Buffer.from('buffer'), 'file2.md', null, undefined, 'file3.txt'));
67
+ const result = getMarkdownFiles();
68
+ expect(result).toEqual(['file1.md', 'file2.md']);
69
+ });
70
+ });
71
+ describe('mapIressComponentToFile', () => {
72
+ beforeEach(() => {
73
+ mockedFs.existsSync.mockReturnValue(true);
74
+ });
75
+ it('should find exact match for component', () => {
76
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray(...mockFileList));
77
+ const mapping = createComponentMapping('IressButton', 'components-button-docs.md');
78
+ const result = mapIressComponentToFile(mapping.componentName);
79
+ expect(result).toBe(mapping.filePath);
80
+ });
81
+ it('should find partial match when exact match is not available', () => {
82
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-advanced-docs.md', 'components-input-docs.md'));
83
+ const mapping = createComponentMapping('IressButton', 'components-button-advanced-docs.md');
84
+ const result = mapIressComponentToFile(mapping.componentName);
85
+ expect(result).toBe(mapping.filePath);
86
+ });
87
+ it('should find fuzzy match when exact and partial matches are not available', () => {
88
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-custom-button-docs.md', 'components-input-docs.md'));
89
+ const mapping = createComponentMapping('IressButton', 'components-custom-button-docs.md');
90
+ const result = mapIressComponentToFile(mapping.componentName);
91
+ expect(result).toBe(mapping.filePath);
92
+ });
93
+ it('should return null when no match is found', () => {
94
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-input-docs.md', 'components-card-docs.md'));
95
+ const mapping = createComponentMapping('IressButton', null);
96
+ const result = mapIressComponentToFile(mapping.componentName);
97
+ expect(result).toBe(mapping.filePath);
98
+ });
99
+ it('should handle component names without Iress prefix', () => {
100
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-docs.md'));
101
+ const mapping = createComponentMapping('Button', 'components-button-docs.md');
102
+ const result = mapIressComponentToFile(mapping.componentName);
103
+ expect(result).toBe(mapping.filePath);
104
+ });
105
+ it('should handle camelCase to lowercase conversion correctly', () => {
106
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-datepicker-docs.md'));
107
+ const mapping = createComponentMapping('IressDatePicker', 'components-datepicker-docs.md');
108
+ const result = mapIressComponentToFile(mapping.componentName);
109
+ expect(result).toBe(mapping.filePath);
110
+ });
111
+ it('should prioritize exact match over partial match', () => {
112
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-button-docs.md', 'components-button-advanced-docs.md'));
113
+ const mapping = createComponentMapping('IressButton', 'components-button-docs.md');
114
+ const result = mapIressComponentToFile(mapping.componentName);
115
+ expect(result).toBe(mapping.filePath);
116
+ });
117
+ it('should prioritize partial match over fuzzy match', () => {
118
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray('components-custom-button-docs.md', 'components-button-advanced-docs.md'));
119
+ const mapping = createComponentMapping('IressButton', 'components-button-advanced-docs.md');
120
+ const result = mapIressComponentToFile(mapping.componentName);
121
+ expect(result).toBe(mapping.filePath);
122
+ });
123
+ });
124
+ describe('extractIressComponents', () => {
125
+ it('should extract Iress component names from text', () => {
126
+ const text = `
127
+ Use IressButton for actions and IressInput for text entry.
128
+ You can also use IressCard to display content.
129
+ `;
130
+ const result = extractIressComponents(text);
131
+ expect(result).toEqual(['IressButton', 'IressInput', 'IressCard']);
132
+ });
133
+ it('should handle empty text', () => {
134
+ const result = extractIressComponents('');
135
+ expect(result).toEqual([]);
136
+ });
137
+ it('should handle text without Iress components', () => {
138
+ const text = 'This is just regular text with no components.';
139
+ const result = extractIressComponents(text);
140
+ expect(result).toEqual([]);
141
+ });
142
+ it('should remove duplicate component names', () => {
143
+ const text = `
144
+ Use IressButton here and IressButton there.
145
+ Also use IressInput and IressButton again.
146
+ `;
147
+ const result = extractIressComponents(text);
148
+ expect(result).toEqual(['IressButton', 'IressInput']);
149
+ });
150
+ it('should match component names with various cases', () => {
151
+ const text = `
152
+ IressA, IressB, IressC, IressABC, IressXYZ,
153
+ IressCamelCase, IressPascalCase
154
+ `;
155
+ const result = extractIressComponents(text);
156
+ expect(result).toEqual([
157
+ 'IressA',
158
+ 'IressB',
159
+ 'IressC',
160
+ 'IressABC',
161
+ 'IressXYZ',
162
+ 'IressCamelCase',
163
+ 'IressPascalCase',
164
+ ]);
165
+ });
166
+ it('should match component names according to current implementation', () => {
167
+ const text = 'ThisIressButtonIsNotValid and IressButton is valid';
168
+ const result = extractIressComponents(text);
169
+ // Current implementation matches any "Iress" followed by capital letter and additional letters
170
+ // This includes compound words like "IressButtonIsNotValid"
171
+ expect(result).toEqual(['IressButtonIsNotValid', 'IressButton']);
172
+ });
173
+ it('should handle special characters and boundaries', () => {
174
+ const text = `
175
+ <IressButton>Click me</IressButton>
176
+ {IressInput}
177
+ IressCard.
178
+ IressModal,
179
+ IressDialog;
180
+ IressTooltip!
181
+ IressForm?
182
+ `;
183
+ const result = extractIressComponents(text);
184
+ expect(result).toEqual([
185
+ 'IressButton',
186
+ 'IressInput',
187
+ 'IressCard',
188
+ 'IressModal',
189
+ 'IressDialog',
190
+ 'IressTooltip',
191
+ 'IressForm',
192
+ ]);
193
+ });
194
+ });
195
+ describe('readFileContent', () => {
196
+ it('should read file content successfully', () => {
197
+ const mockContent = 'Mock file content';
198
+ mockedFs.readFileSync.mockReturnValue(mockContent);
199
+ const result = readFileContent('/path/to/file.txt');
200
+ expect(result).toBe(mockContent);
201
+ expect(fs.readFileSync).toHaveBeenCalledWith('/path/to/file.txt', 'utf-8');
202
+ });
203
+ it('should propagate file system errors', () => {
204
+ const error = new Error('File not found');
205
+ mockedFs.readFileSync.mockImplementation(() => {
206
+ throw error;
207
+ });
208
+ expect(() => readFileContent('/nonexistent/file.txt')).toThrow('File not found');
209
+ });
210
+ it('should handle different file paths', () => {
211
+ mockedFs.readFileSync.mockReturnValue('content');
212
+ readFileContent('/absolute/path/file.txt');
213
+ expect(fs.readFileSync).toHaveBeenCalledWith('/absolute/path/file.txt', 'utf-8');
214
+ readFileContent('relative/path/file.txt');
215
+ expect(fs.readFileSync).toHaveBeenCalledWith('relative/path/file.txt', 'utf-8');
216
+ });
217
+ });
218
+ describe('fileExists', () => {
219
+ it('should return true when file exists', () => {
220
+ mockedFs.existsSync.mockReturnValue(true);
221
+ const result = fileExists('/path/to/file.txt');
222
+ expect(result).toBe(true);
223
+ expect(fs.existsSync).toHaveBeenCalledWith('/path/to/file.txt');
224
+ });
225
+ it('should return false when file does not exist', () => {
226
+ mockedFs.existsSync.mockReturnValue(false);
227
+ const result = fileExists('/nonexistent/file.txt');
228
+ expect(result).toBe(false);
229
+ expect(fs.existsSync).toHaveBeenCalledWith('/nonexistent/file.txt');
230
+ });
231
+ it('should handle different file paths', () => {
232
+ mockedFs.existsSync.mockReturnValue(true);
233
+ fileExists('/absolute/path/file.txt');
234
+ expect(fs.existsSync).toHaveBeenCalledWith('/absolute/path/file.txt');
235
+ fileExists('relative/path/file.txt');
236
+ expect(fs.existsSync).toHaveBeenCalledWith('relative/path/file.txt');
237
+ });
238
+ it('should handle edge cases', () => {
239
+ mockedFs.existsSync.mockReturnValue(false);
240
+ expect(fileExists('')).toBe(false);
241
+ expect(fileExists(' ')).toBe(false);
242
+ expect(fileExists('.')).toBe(false);
243
+ expect(fileExists('..')).toBe(false);
244
+ });
245
+ });
246
+ describe('type safety and helper functions', () => {
247
+ it('should create valid ComponentMapping objects', () => {
248
+ const validMapping = createComponentMapping('IressButton', 'components-button-docs.md');
249
+ const nullMapping = createComponentMapping('IressNonExistent', null);
250
+ expect(validMapping).toEqual({
251
+ componentName: 'IressButton',
252
+ filePath: 'components-button-docs.md',
253
+ });
254
+ expect(nullMapping).toEqual({
255
+ componentName: 'IressNonExistent',
256
+ filePath: null,
257
+ });
258
+ });
259
+ it('should work with mock file list type', () => {
260
+ const mockFile = 'components-button-docs.md';
261
+ expect(mockFileList).toContain(mockFile);
262
+ // Type checking ensures we can only use valid file names
263
+ expect(typeof mockFile).toBe('string');
264
+ expect(mockFile.endsWith('.md')).toBe(true);
265
+ });
266
+ it('should demonstrate type-safe component mapping workflow', () => {
267
+ mockedFs.existsSync.mockReturnValue(true);
268
+ mockedFs.readdirSync.mockReturnValue(createMockFileArray(...mockFileList));
269
+ const componentMappings = [
270
+ createComponentMapping('IressButton', null),
271
+ createComponentMapping('IressInput', null),
272
+ createComponentMapping('IressCard', null),
273
+ ];
274
+ // Test that all components get properly mapped
275
+ const results = componentMappings.map((mapping) => ({
276
+ ...mapping,
277
+ filePath: mapIressComponentToFile(mapping.componentName),
278
+ }));
279
+ expect(results).toEqual([
280
+ { componentName: 'IressButton', filePath: 'components-button-docs.md' },
281
+ { componentName: 'IressInput', filePath: 'components-input-docs.md' },
282
+ { componentName: 'IressCard', filePath: 'components-card-docs.md' },
283
+ ]);
284
+ });
285
+ });
286
+ });
@@ -29,7 +29,7 @@ Hide code
29
29
  }
30
30
  \]}
31
31
  popoverProps\={{
32
- container: {}
32
+ container: document.body
33
33
  }}
34
34
  />
35
35
 
@@ -203,6 +203,50 @@ export const AutocompleteUsingAsync \= () \=> (
203
203
 
204
204
  Copy
205
205
 
206
+ #### [](#minimum-search-length-for-async-options)Minimum search length for async options
207
+
208
+ When using asynchronous options, you can set a minimum number of characters required before triggering the search using the `minSearchLength` prop. This prevents unnecessary API calls and loading states for very short queries.
209
+
210
+ By default, async searches are triggered after 1 character. Setting a higher value (e.g., 3) means no search request will be made and no loading spinner will appear until the user types at least that many characters.
211
+
212
+ Hide code
213
+
214
+ \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
215
+
216
+ import { IressAutocomplete, IressAutocompleteProps } from '@iress-oss/ids-components';
217
+ interface StarWarsCharacter {
218
+ name: string;
219
+ gender: string;
220
+ }
221
+ interface StarWarsCharacterApi {
222
+ results: StarWarsCharacter\[\];
223
+ }
224
+ export const AutocompleteUsingAsync \= () \=> (
225
+ <IressAutocomplete
226
+ {...{
227
+ popoverProps: {
228
+ container: document.body,
229
+ },
230
+ minSearchLength: 3,
231
+ }}
232
+ options\={async (query: string) \=> {
233
+ if (query \=== 'error') {
234
+ throw new Error('This is an error');
235
+ }
236
+ const data \= await fetch(
237
+ \`https://swapi.py4e.com/api/people/?search=${query}\`,
238
+ ).then((response) \=> response.json() as Promise<StarWarsCharacterApi\>);
239
+ return data.results.map((character: StarWarsCharacter) \=> ({
240
+ label: character.name,
241
+ value: character.name,
242
+ meta: character.gender,
243
+ }));
244
+ }}
245
+ />
246
+ );
247
+
248
+ Copy
249
+
206
250
  #### [](#initialoptions)`initialOptions`
207
251
 
208
252
  If you want to provide initial options to the user, you can use the `initialOptions` prop. This is useful when you want to provide a list of options to the user before they start typing (eg. recommended search terms).
@@ -241,7 +285,7 @@ Hide code
241
285
  }
242
286
  \]}
243
287
  popoverProps\={{
244
- container: {}
288
+ container: document.body
245
289
  }}
246
290
  />
247
291
 
@@ -450,7 +494,7 @@ Hide code
450
494
  \]}
451
495
  placeholder\="Instant search!"
452
496
  popoverProps\={{
453
- container: document.body
497
+ container: {}
454
498
  }}
455
499
  />
456
500
 
@@ -197,22 +197,22 @@ Hide code
197
197
  stack </h3\>
198
198
  <IressCheckboxGroup layout\="stack"\>
199
199
  <IressCheckbox
200
- className\="ids-styles--add-border-to-label-v5150"
200
+ className\="ids-styles--add-border-to-label-v5200"
201
201
  value\="google"
202
202
  \>
203
203
  Google </IressCheckbox\>
204
204
  <IressCheckbox
205
- className\="ids-styles--add-border-to-label-v5150"
205
+ className\="ids-styles--add-border-to-label-v5200"
206
206
  value\="newspaper"
207
207
  \>
208
208
  Newspaper </IressCheckbox\>
209
209
  <IressCheckbox
210
- className\="ids-styles--add-border-to-label-v5150"
210
+ className\="ids-styles--add-border-to-label-v5200"
211
211
  value\="friend"
212
212
  \>
213
213
  Friend </IressCheckbox\>
214
214
  <IressCheckbox
215
- className\="ids-styles--add-border-to-label-v5150"
215
+ className\="ids-styles--add-border-to-label-v5200"
216
216
  value\="other"
217
217
  \>
218
218
  Other </IressCheckbox\>
@@ -223,22 +223,22 @@ Hide code
223
223
  block </h3\>
224
224
  <IressCheckboxGroup layout\="block"\>
225
225
  <IressCheckbox
226
- className\="ids-styles--add-border-to-label-v5150"
226
+ className\="ids-styles--add-border-to-label-v5200"
227
227
  value\="google"
228
228
  \>
229
229
  Google </IressCheckbox\>
230
230
  <IressCheckbox
231
- className\="ids-styles--add-border-to-label-v5150"
231
+ className\="ids-styles--add-border-to-label-v5200"
232
232
  value\="newspaper"
233
233
  \>
234
234
  Newspaper </IressCheckbox\>
235
235
  <IressCheckbox
236
- className\="ids-styles--add-border-to-label-v5150"
236
+ className\="ids-styles--add-border-to-label-v5200"
237
237
  value\="friend"
238
238
  \>
239
239
  Friend </IressCheckbox\>
240
240
  <IressCheckbox
241
- className\="ids-styles--add-border-to-label-v5150"
241
+ className\="ids-styles--add-border-to-label-v5200"
242
242
  value\="other"
243
243
  \>
244
244
  Other </IressCheckbox\>
@@ -249,22 +249,22 @@ Hide code
249
249
  inline </h3\>
250
250
  <IressCheckboxGroup layout\="inline"\>
251
251
  <IressCheckbox
252
- className\="ids-styles--add-border-to-label-v5150"
252
+ className\="ids-styles--add-border-to-label-v5200"
253
253
  value\="google"
254
254
  \>
255
255
  Google </IressCheckbox\>
256
256
  <IressCheckbox
257
- className\="ids-styles--add-border-to-label-v5150"
257
+ className\="ids-styles--add-border-to-label-v5200"
258
258
  value\="newspaper"
259
259
  \>
260
260
  Newspaper </IressCheckbox\>
261
261
  <IressCheckbox
262
- className\="ids-styles--add-border-to-label-v5150"
262
+ className\="ids-styles--add-border-to-label-v5200"
263
263
  value\="friend"
264
264
  \>
265
265
  Friend </IressCheckbox\>
266
266
  <IressCheckbox
267
- className\="ids-styles--add-border-to-label-v5150"
267
+ className\="ids-styles--add-border-to-label-v5200"
268
268
  value\="other"
269
269
  \>
270
270
  Other </IressCheckbox\>
@@ -275,22 +275,22 @@ Hide code
275
275
  full </h3\>
276
276
  <IressCheckboxGroup layout\="full"\>
277
277
  <IressCheckbox
278
- className\="ids-styles--add-border-to-label-v5150"
278
+ className\="ids-styles--add-border-to-label-v5200"
279
279
  value\="google"
280
280
  \>
281
281
  Google </IressCheckbox\>
282
282
  <IressCheckbox
283
- className\="ids-styles--add-border-to-label-v5150"
283
+ className\="ids-styles--add-border-to-label-v5200"
284
284
  value\="newspaper"
285
285
  \>
286
286
  Newspaper </IressCheckbox\>
287
287
  <IressCheckbox
288
- className\="ids-styles--add-border-to-label-v5150"
288
+ className\="ids-styles--add-border-to-label-v5200"
289
289
  value\="friend"
290
290
  \>
291
291
  Friend </IressCheckbox\>
292
292
  <IressCheckbox
293
- className\="ids-styles--add-border-to-label-v5150"
293
+ className\="ids-styles--add-border-to-label-v5200"
294
294
  value\="other"
295
295
  \>
296
296
  Other </IressCheckbox\>
@@ -445,7 +445,7 @@ Hide code
445
445
  }}
446
446
  \>
447
447
  <div
448
- className\="ids-styles--resizable-v5150"
448
+ className\="ids-styles--resizable-v5200"
449
449
  style\={{
450
450
  display: 'grid',
451
451
  gridAutoRows: '1fr',
@@ -429,7 +429,7 @@ Hide code
429
429
 
430
430
  <IressContainer\>
431
431
  <IressRow
432
- className\="ids-styles--set-height-v5150"
432
+ className\="ids-styles--set-height-v5200"
433
433
  gutter\="md"
434
434
  \>
435
435
  <IressCol alignSelf\="start"\>
@@ -44,7 +44,7 @@ Hide code
44
44
  }
45
45
  \]}
46
46
  popoverProps\={{
47
- container: {}
47
+ container: document.body
48
48
  }}
49
49
  />
50
50
 
@@ -195,7 +195,7 @@ Hide code
195
195
  }
196
196
  \]}
197
197
  popoverProps\={{
198
- container: document.body
198
+ container: {}
199
199
  }}
200
200
  />
201
201
 
@@ -533,7 +533,7 @@ Hide code
533
533
  \]}
534
534
  placeholder\="Instant search!"
535
535
  popoverProps\={{
536
- container: {}
536
+ container: document.body
537
537
  }}
538
538
  />
539
539
 
@@ -794,7 +794,7 @@ Hide code
794
794
  }
795
795
  \]}
796
796
  popoverProps\={{
797
- container: document.body
797
+ container: {}
798
798
  }}
799
799
  selectedOptionsTagText\="options selected"
800
800
  />
@@ -39,7 +39,7 @@ Hide code
39
39
  }
40
40
  \]}
41
41
  popoverProps\={{
42
- container: {}
42
+ container: document.body
43
43
  }}
44
44
  />
45
45
 
@@ -538,7 +538,7 @@ Hide code
538
538
  }
539
539
  \]}
540
540
  popoverProps\={{
541
- container: {}
541
+ container: document.body
542
542
  }}
543
543
  />
544
544
 
@@ -850,7 +850,7 @@ Hide code
850
850
  }
851
851
  \]}
852
852
  popoverProps\={{
853
- container: document.body
853
+ container: {}
854
854
  }}
855
855
  searchable
856
856
  />
@@ -205,6 +205,8 @@ Salad
205
205
 
206
206
  Type to copy an existing character's name
207
207
 
208
+ Type at least 1 character to search
209
+
208
210
  \*Required Your star wars sidekick
209
211
 
210
212
  None selected
@@ -466,42 +468,7 @@ Enter a maximum length of 5 characters
466
468
 
467
469
  Validate
468
470
 
469
- Hide code
470
-
471
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
472
-
473
- <IressForm\>
474
- <IressStack gutter\="lg"\>
475
- <IressFormField
476
- hint\="Enter a maximum length of 5 characters"
477
- label\="Default message"
478
- name\="IressInput-default"
479
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
480
- rules\={{
481
- maxLength: 5
482
- }}
483
- />
484
- <IressFormField
485
- hint\="Enter a maximum length of 5 characters"
486
- label\="Custom message"
487
- name\="IressInput-custom"
488
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
489
- rules\={{
490
- maxLength: {
491
- message: 'Please enter a max length of 5 characters!',
492
- value: 5
493
- }
494
- }}
495
- />
496
- <IressButton
497
- mode\="primary"
498
- type\="submit"
499
- \>
500
- Validate </IressButton\>
501
- </IressStack\>
502
- </IressForm\>
503
-
504
- Copy
471
+ Show code
505
472
 
506
473
  #### [](#minlength)`minLength`
507
474
 
@@ -747,7 +714,7 @@ Hide code
747
714
  name\="IressInputDate-default"
748
715
  render\={(controlledProps) \=> <IressInput {...controlledProps} />}
749
716
  rules\={{
750
- minDate: new Date('2025-07-10T05:30:17.621Z')
717
+ minDate: new Date('2025-09-11T06:12:16.799Z')
751
718
  }}
752
719
  />
753
720
  <IressFormField
@@ -758,7 +725,7 @@ Hide code
758
725
  rules\={{
759
726
  minDate: {
760
727
  message: 'Please enter a date after today!',
761
- value: new Date('2025-07-10T05:30:17.621Z')
728
+ value: new Date('2025-09-11T06:12:16.799Z')
762
729
  }
763
730
  }}
764
731
  />
@@ -800,7 +767,7 @@ Hide code
800
767
  name\="IressInputDate-default"
801
768
  render\={(controlledProps) \=> <IressInput {...controlledProps} />}
802
769
  rules\={{
803
- maxDate: new Date('2025-07-10T05:30:17.621Z')
770
+ maxDate: new Date('2025-09-11T06:12:16.799Z')
804
771
  }}
805
772
  />
806
773
  <IressFormField
@@ -811,7 +778,7 @@ Hide code
811
778
  rules\={{
812
779
  maxDate: {
813
780
  message: 'Please enter a date before today!',
814
- value: new Date('2025-07-10T05:30:17.621Z')
781
+ value: new Date('2025-09-11T06:12:16.799Z')
815
782
  }
816
783
  }}
817
784
  />
@@ -467,13 +467,13 @@ Hide code
467
467
  \>
468
468
  Default width </IressText\>
469
469
  <IressIcon
470
- className\="ids-styles--alt-background-v5150"
470
+ className\="ids-styles--alt-background-v5200"
471
471
  name\="space-shuttle"
472
472
  size\="3x"
473
473
  />
474
474
  <br />
475
475
  <IressIcon
476
- className\="ids-styles--alt-background-v5150"
476
+ className\="ids-styles--alt-background-v5200"
477
477
  name\="wine-glass-alt"
478
478
  size\="3x"
479
479
  />
@@ -485,14 +485,14 @@ Hide code
485
485
  \>
486
486
  Fixed width </IressText\>
487
487
  <IressIcon
488
- className\="ids-styles--alt-background-v5150"
488
+ className\="ids-styles--alt-background-v5200"
489
489
  fixedWidth
490
490
  name\="space-shuttle"
491
491
  size\="3x"
492
492
  />
493
493
  <br />
494
494
  <IressIcon
495
- className\="ids-styles--alt-background-v5150"
495
+ className\="ids-styles--alt-background-v5200"
496
496
  fixedWidth
497
497
  name\="wine-glass-alt"
498
498
  size\="3x"