@neo4j-ndl/react 4.18.4 → 4.18.6
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/lib/LICENSES.txt +30 -4
- package/lib/cjs/kbd/Kbd.js +3 -0
- package/lib/cjs/kbd/Kbd.js.map +1 -1
- package/lib/cjs/menu/Menu.js +60 -42
- package/lib/cjs/menu/Menu.js.map +1 -1
- package/lib/cjs/menu/stories/menu-in-dialog.story.js +3 -5
- package/lib/cjs/menu/stories/menu-in-dialog.story.js.map +1 -1
- package/lib/esm/kbd/Kbd.js +3 -0
- package/lib/esm/kbd/Kbd.js.map +1 -1
- package/lib/esm/menu/Menu.js +60 -42
- package/lib/esm/menu/Menu.js.map +1 -1
- package/lib/esm/menu/stories/menu-in-dialog.story.js +3 -5
- package/lib/esm/menu/stories/menu-in-dialog.story.js.map +1 -1
- package/lib/types/kbd/Kbd.d.ts +1 -1
- package/lib/types/kbd/Kbd.d.ts.map +1 -1
- package/lib/types/menu/Menu.d.ts.map +1 -1
- package/lib/types/menu/stories/menu-in-dialog.story.d.ts.map +1 -1
- package/package.json +3 -3
- package/skills/ndl-react/SKILL.md +4 -4
- package/skills/ndl-react/components/ai/response.md +5 -5
- package/skills/ndl-react/components/color-picker.md +78 -0
- package/skills/ndl-react/components/menu.md +42 -41
- package/skills/ndl-react/components/time-picker.md +44 -0
- package/skills/ndl-react/components/timezone-picker.md +43 -0
|
@@ -9,7 +9,9 @@ Import: `import { ColorPicker } from '@neo4j-ndl/react'`
|
|
|
9
9
|
| Prop | Type | Required | Default | Description |
|
|
10
10
|
|------|------|----------|---------|-------------|
|
|
11
11
|
| `color` | `` HsvaColor \| RgbaColor \| `#${string}` `` | ✅ | | The current color value. Can be provided in HSVA, RGBA, or Hex format. The component will automatically convert between formats as needed. |
|
|
12
|
+
| `floatingStrategy` | `'absolute' \| 'fixed'` | | `absolute` | The floating strategy to use for the menu. If not provided, the menu will be positioned absolutely. |
|
|
12
13
|
| `onChange` | `` (newColor: { hex: `#${string}`; rgb: RgbaColor; hsva: HsvaColor; }) => void `` | ✅ | | Callback function triggered when the color value changes. Receives an object containing the new color in all three formats (hex, rgb, hsva) for convenience. |
|
|
14
|
+
| `portalTarget` | `HTMLElement \| null` | | | The target element to portal the menu to. If not provided, the menu will not be portaled. |
|
|
13
15
|
| `shouldShowEyeDropper` | `boolean` | | `true` | Whether to display the eye dropper tool that allows users to sample colors from anywhere on the screen. |
|
|
14
16
|
| `swatches` | `` (HsvaColor \| RgbaColor \| `#${string}`)[] `` | | `Object.values(tokens.graph).filter(validHex)` | Optional array of predefined color swatches for quick selection. Each swatch can be in HSVA, RGBA, or Hex format. |
|
|
15
17
|
|
|
@@ -103,6 +105,82 @@ const Component = () => {
|
|
|
103
105
|
export default Component;
|
|
104
106
|
```
|
|
105
107
|
|
|
108
|
+
### Dialog
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
|
|
112
|
+
|
|
113
|
+
import { ColorPicker, Dialog, FilledButton } from '@neo4j-ndl/react';
|
|
114
|
+
import { useState } from 'react';
|
|
115
|
+
|
|
116
|
+
const Component = () => {
|
|
117
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
118
|
+
const handleClick = () => setIsOpen((prev) => !prev);
|
|
119
|
+
const handleClose = () => setIsOpen(false);
|
|
120
|
+
|
|
121
|
+
const [color, setColor] = useState({
|
|
122
|
+
a: 1,
|
|
123
|
+
b: 0,
|
|
124
|
+
g: 0,
|
|
125
|
+
r: 0,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
<div className="n-flex n-items-center n-justify-centern-w-full">
|
|
130
|
+
<FilledButton
|
|
131
|
+
onClick={handleClick}
|
|
132
|
+
htmlAttributes={{ 'aria-haspopup': 'dialog' }}
|
|
133
|
+
>
|
|
134
|
+
Open Dialog
|
|
135
|
+
</FilledButton>
|
|
136
|
+
<Dialog onClose={handleClose} isOpen={isOpen}>
|
|
137
|
+
<Dialog.Header>Header</Dialog.Header>
|
|
138
|
+
<Dialog.Content className="n-max-h-96 n-overflow-y-auto">
|
|
139
|
+
<ColorPicker
|
|
140
|
+
color={color}
|
|
141
|
+
onChange={(newColor) => setColor(newColor.rgb)}
|
|
142
|
+
floatingStrategy="fixed"
|
|
143
|
+
/>
|
|
144
|
+
</Dialog.Content>
|
|
145
|
+
</Dialog>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default Component;
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Popover
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
|
|
157
|
+
|
|
158
|
+
import { ColorPicker, FilledButton, Popover } from '@neo4j-ndl/react';
|
|
159
|
+
|
|
160
|
+
const Component = () => {
|
|
161
|
+
return (
|
|
162
|
+
<Popover>
|
|
163
|
+
<Popover.Trigger hasButtonWrapper>
|
|
164
|
+
<FilledButton>Open Popover</FilledButton>
|
|
165
|
+
</Popover.Trigger>
|
|
166
|
+
<Popover.Content className="n-overflow-y-auto n-overflow-x-hidden n-p-4 n-max-h-64">
|
|
167
|
+
Popover content
|
|
168
|
+
<ColorPicker
|
|
169
|
+
color="#ff0000"
|
|
170
|
+
onChange={() => {
|
|
171
|
+
console.info('color changed');
|
|
172
|
+
}}
|
|
173
|
+
floatingStrategy="fixed"
|
|
174
|
+
portalTarget={document.body}
|
|
175
|
+
/>
|
|
176
|
+
</Popover.Content>
|
|
177
|
+
</Popover>
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export default Component;
|
|
182
|
+
```
|
|
183
|
+
|
|
106
184
|
### Without Eyedropper
|
|
107
185
|
|
|
108
186
|
```tsx
|
|
@@ -111,7 +111,7 @@ Implements the keyboard interactions defined in the [WAI-ARIA menu pattern](http
|
|
|
111
111
|
| `Space` | Activates the focused menu item |
|
|
112
112
|
| `Tab` | Closes the menu and moves focus to the next focusable element on the page |
|
|
113
113
|
| `Shift + Tab` | Closes the menu and moves focus to the previous focusable element on the page |
|
|
114
|
-
| `Escape` | Closes the menu and returns focus to the trigger |
|
|
114
|
+
| `Escape` | Closes the full menu tree and returns focus to the trigger. The event does not propagate beyond the root menu, so enclosing overlays remain open |
|
|
115
115
|
| Type-ahead | Typing a character moves focus to the next item starting with that character |
|
|
116
116
|
|
|
117
117
|
## WAI-ARIA roles and attributes
|
|
@@ -301,50 +301,51 @@ const Component = () => {
|
|
|
301
301
|
isOpen={isModalOpen}
|
|
302
302
|
onClose={handleClose}
|
|
303
303
|
>
|
|
304
|
-
<
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
anchorRef={anchorEl}
|
|
317
|
-
onClose={(event, _data) => {
|
|
318
|
-
setIsOpen(false);
|
|
319
|
-
event?.preventDefault();
|
|
320
|
-
event?.stopPropagation();
|
|
321
|
-
}}
|
|
322
|
-
portalTarget={document.getElementById('modal-root')}
|
|
323
|
-
htmlAttributes={{ id: 'dialog-menu' }}
|
|
324
|
-
>
|
|
325
|
-
<Menu.Item title="Undo" onClick={() => alert('Undo')} />
|
|
326
|
-
<Menu.Item title="Redo" isDisabled />
|
|
327
|
-
<Menu.Item title="Cut" description="Copy and remove" />
|
|
304
|
+
<Dialog.Header>Menu in Dialog</Dialog.Header>
|
|
305
|
+
<Dialog.Content>
|
|
306
|
+
<div className="n-flex n-justify-center">
|
|
307
|
+
<FilledButton
|
|
308
|
+
onClick={handleMenuClick}
|
|
309
|
+
ref={anchorEl}
|
|
310
|
+
aria-haspopup="menu"
|
|
311
|
+
aria-expanded={isOpen}
|
|
312
|
+
>
|
|
313
|
+
Open Menu
|
|
314
|
+
</FilledButton>
|
|
315
|
+
</div>
|
|
328
316
|
<Menu
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
317
|
+
isOpen={isOpen}
|
|
318
|
+
anchorRef={anchorEl}
|
|
319
|
+
onClose={(_event, _data) => {
|
|
320
|
+
setIsOpen(false);
|
|
321
|
+
}}
|
|
322
|
+
portalTarget={document.getElementById('modal-root')}
|
|
323
|
+
htmlAttributes={{ id: 'dialog-menu' }}
|
|
332
324
|
>
|
|
333
|
-
<Menu.Item title="
|
|
334
|
-
<Menu.Item title="
|
|
335
|
-
<Menu title="
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
<
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
<Menu
|
|
344
|
-
|
|
325
|
+
<Menu.Item title="Undo" onClick={() => alert('Undo')} />
|
|
326
|
+
<Menu.Item title="Redo" isDisabled />
|
|
327
|
+
<Menu.Item title="Cut" description="Copy and remove" />
|
|
328
|
+
<Menu
|
|
329
|
+
title="Copy as"
|
|
330
|
+
description="Copying as something"
|
|
331
|
+
icon={<Square2StackIconOutline />}
|
|
332
|
+
>
|
|
333
|
+
<Menu.Item title="Text" />
|
|
334
|
+
<Menu.Item title="Video" />
|
|
335
|
+
<Menu title="Image">
|
|
336
|
+
<Menu.Item title=".png" />
|
|
337
|
+
<Menu.Item title=".jpg" />
|
|
338
|
+
<Menu.Item title=".svg" />
|
|
339
|
+
<Menu.Item title=".gif" />
|
|
340
|
+
</Menu>
|
|
341
|
+
<Menu.Item title="Audio" />
|
|
342
|
+
<Menu title="Share">
|
|
343
|
+
<Menu.Item title="Mail" />
|
|
344
|
+
<Menu.Item title="Instagram" />
|
|
345
|
+
</Menu>
|
|
345
346
|
</Menu>
|
|
346
347
|
</Menu>
|
|
347
|
-
</
|
|
348
|
+
</Dialog.Content>
|
|
348
349
|
</Dialog>
|
|
349
350
|
</>
|
|
350
351
|
);
|
|
@@ -109,6 +109,50 @@ const Component = () => {
|
|
|
109
109
|
export default Component;
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
### In Popover Dialog
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
|
|
116
|
+
|
|
117
|
+
import {
|
|
118
|
+
Dialog,
|
|
119
|
+
FilledButton,
|
|
120
|
+
type NeedleTime,
|
|
121
|
+
Popover,
|
|
122
|
+
TimePicker,
|
|
123
|
+
} from '@neo4j-ndl/react';
|
|
124
|
+
import { useState } from 'react';
|
|
125
|
+
|
|
126
|
+
const Component = () => {
|
|
127
|
+
const [selectedTime, setSelectedTime] = useState<NeedleTime>();
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Dialog isOpen={true} aria-label="Dialog">
|
|
131
|
+
<Dialog.Header>
|
|
132
|
+
Using Time Picker inside a popover in a dialog
|
|
133
|
+
</Dialog.Header>
|
|
134
|
+
<Dialog.Description className="n-flex n-flex-col n-gap-token-32">
|
|
135
|
+
<Popover>
|
|
136
|
+
<Popover.Trigger hasButtonWrapper>
|
|
137
|
+
<FilledButton>Open Popover</FilledButton>
|
|
138
|
+
</Popover.Trigger>
|
|
139
|
+
<Popover.Content className="n-p-token-16">
|
|
140
|
+
<TimePicker
|
|
141
|
+
label="Select Time"
|
|
142
|
+
value={selectedTime}
|
|
143
|
+
onChange={(time) => setSelectedTime(time)}
|
|
144
|
+
htmlAttributes={{ id: 'time-picker-input' }}
|
|
145
|
+
/>
|
|
146
|
+
</Popover.Content>
|
|
147
|
+
</Popover>
|
|
148
|
+
</Dialog.Description>
|
|
149
|
+
</Dialog>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default Component;
|
|
154
|
+
```
|
|
155
|
+
|
|
112
156
|
### With Seconds
|
|
113
157
|
|
|
114
158
|
```tsx
|
|
@@ -382,6 +382,49 @@ const Component = () => {
|
|
|
382
382
|
export default Component;
|
|
383
383
|
```
|
|
384
384
|
|
|
385
|
+
### In Popover Dialog
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
|
|
389
|
+
|
|
390
|
+
import {
|
|
391
|
+
Dialog,
|
|
392
|
+
FilledButton,
|
|
393
|
+
Popover,
|
|
394
|
+
TimeZonePicker,
|
|
395
|
+
} from '@neo4j-ndl/react';
|
|
396
|
+
import { useState } from 'react';
|
|
397
|
+
|
|
398
|
+
const Component = () => {
|
|
399
|
+
const [selectedTimeZone, setSelectedTimeZone] = useState<string>('UTC');
|
|
400
|
+
|
|
401
|
+
return (
|
|
402
|
+
<Dialog isOpen={true} aria-label="Dialog">
|
|
403
|
+
<Dialog.Header>
|
|
404
|
+
Using Timezone Picker inside a popover in a dialog
|
|
405
|
+
</Dialog.Header>
|
|
406
|
+
<Dialog.Description className="n-flex n-flex-col n-gap-token-32">
|
|
407
|
+
<Popover>
|
|
408
|
+
<Popover.Trigger hasButtonWrapper>
|
|
409
|
+
<FilledButton>Open Popover</FilledButton>
|
|
410
|
+
</Popover.Trigger>
|
|
411
|
+
<Popover.Content className="n-p-token-16">
|
|
412
|
+
<TimeZonePicker
|
|
413
|
+
label="Timezone"
|
|
414
|
+
value={selectedTimeZone}
|
|
415
|
+
onChange={setSelectedTimeZone}
|
|
416
|
+
htmlAttributes={{ id: 'time-zone-input' }}
|
|
417
|
+
/>
|
|
418
|
+
</Popover.Content>
|
|
419
|
+
</Popover>
|
|
420
|
+
</Dialog.Description>
|
|
421
|
+
</Dialog>
|
|
422
|
+
);
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
export default Component;
|
|
426
|
+
```
|
|
427
|
+
|
|
385
428
|
### Sizes
|
|
386
429
|
|
|
387
430
|
```tsx
|