@overdoser/react-toolkit 0.0.9 → 0.0.11
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/AGENTS.md +1 -0
- package/components/Dropdown/Dropdown.d.ts +11 -0
- package/components/inputs/Select/Select.d.ts +9 -0
- package/hooks/usePortalPosition.d.ts +18 -0
- package/index.css +1 -1
- package/index.js +1934 -1838
- package/llms.txt +2 -0
- package/manifest.json +4 -1
- package/package.json +1 -1
- package/recipes/multi-select-in-modal.tsx +74 -0
package/llms.txt
CHANGED
|
@@ -193,6 +193,7 @@ Two distinct usage modes — pick one:
|
|
|
193
193
|
- `align?: 'left' | 'right'` — default `'left'`. Menu alignment relative to trigger.
|
|
194
194
|
- `error?: boolean` — default `false`
|
|
195
195
|
- `fullWidth?: boolean` — default `true`
|
|
196
|
+
- `portal?: boolean` — default `true`. The open menu is rendered in a portal at `document.body` so it escapes `overflow: hidden` ancestors (Modal body, scroll containers). Uses `--crk-z-floating` (1060) which sits above `--crk-z-modal` (1050). Set to `false` if you need the menu in the trigger's DOM subtree (e.g., parent-scoped CSS theming).
|
|
196
197
|
- `id?: string`
|
|
197
198
|
- `onOpen?: () => void`
|
|
198
199
|
- `onClose?: () => void`
|
|
@@ -370,6 +371,7 @@ Props:
|
|
|
370
371
|
- `allowCreate?: boolean` — default `false`. Multi-mode only. Adds a "Create '<query>'" row when the search query doesn't match an existing option. Pressing Enter (or clicking the row) pushes the trimmed query into `onValuesChange` and fires `onCreate`.
|
|
371
372
|
- `onCreate?: (value: string) => void` — Multi-mode only, paired with `allowCreate`. Fires with the new value; consumers typically persist it (e.g. push it back into `options`).
|
|
372
373
|
- `createLabel?: (query: string) => ReactNode` — Multi-mode only. Custom render for the create row. Default: `Create "<query>"`.
|
|
374
|
+
- `portal?: boolean` — default `true`. Applies to `searchable` + `multiple` modes (native `<select>` is unaffected). The open menu is rendered in a portal at `document.body` with `position: fixed` + `--crk-z-floating` (1060), so it escapes `overflow: hidden` ancestors and sits above `--crk-z-modal` (1050). Means a `<Select>` inside a `<Modal>` works without needing to size the modal. Pass `false` if you need the menu inside the trigger's subtree.
|
|
373
375
|
- `classes?: Partial<SelectClasses>` where `SelectClasses = { wrapper, root, arrow, search, menu, item, chip, chipRemove }`
|
|
374
376
|
|
|
375
377
|
Searchable example:
|
package/manifest.json
CHANGED
|
@@ -124,6 +124,7 @@
|
|
|
124
124
|
"align": { "type": "enum", "values": ["left", "right"], "default": "left" },
|
|
125
125
|
"error": { "type": "boolean", "default": false },
|
|
126
126
|
"fullWidth": { "type": "boolean", "default": true },
|
|
127
|
+
"portal": { "type": "boolean", "default": true, "notes": "Renders the open menu in a portal at document.body using --crk-z-floating (1060). Escapes overflow:hidden ancestors and sits above modals. Set false to keep the menu in the trigger's subtree." },
|
|
127
128
|
"id": { "type": "string" },
|
|
128
129
|
"onOpen": { "type": "() => void" },
|
|
129
130
|
"onClose": { "type": "() => void" },
|
|
@@ -256,6 +257,7 @@
|
|
|
256
257
|
"allowCreate": { "type": "boolean", "default": false, "notes": "Multi-mode only. Adds a 'Create <query>' row when the query doesn't match an existing option; pressing Enter (or clicking it) pushes the trimmed query into onValuesChange and fires onCreate." },
|
|
257
258
|
"onCreate": { "type": "(value: string) => void", "notes": "Multi-mode only. Paired with allowCreate." },
|
|
258
259
|
"createLabel": { "type": "(query: string) => ReactNode", "notes": "Multi-mode only. Custom render for the Create row." },
|
|
260
|
+
"portal": { "type": "boolean", "default": true, "notes": "Applies to searchable + multiple modes. Renders the open menu in a portal at document.body using --crk-z-floating (1060) — escapes overflow:hidden ancestors and sits above modals. Set false to keep the menu in the trigger's subtree." },
|
|
259
261
|
"classes": { "type": "Partial<SelectClasses>", "shape": ["wrapper", "root", "arrow", "search", "menu", "item", "chip", "chipRemove"] }
|
|
260
262
|
}
|
|
261
263
|
},
|
|
@@ -663,6 +665,7 @@
|
|
|
663
665
|
"recipes/interactive-area-chart.tsx",
|
|
664
666
|
"recipes/interactive-pie-chart.tsx",
|
|
665
667
|
"recipes/trading-chart.tsx",
|
|
666
|
-
"recipes/tag-input.tsx"
|
|
668
|
+
"recipes/tag-input.tsx",
|
|
669
|
+
"recipes/multi-select-in-modal.tsx"
|
|
667
670
|
]
|
|
668
671
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Button, Modal, Select } from '@overdoser/react-toolkit';
|
|
3
|
+
|
|
4
|
+
const TAGS = [
|
|
5
|
+
{ value: 'react', label: 'React' },
|
|
6
|
+
{ value: 'typescript', label: 'TypeScript' },
|
|
7
|
+
{ value: 'rust', label: 'Rust' },
|
|
8
|
+
{ value: 'go', label: 'Go' },
|
|
9
|
+
{ value: 'python', label: 'Python' },
|
|
10
|
+
{ value: 'graphql', label: 'GraphQL' },
|
|
11
|
+
{ value: 'css', label: 'CSS' },
|
|
12
|
+
{ value: 'docker', label: 'Docker' },
|
|
13
|
+
{ value: 'kubernetes', label: 'Kubernetes' },
|
|
14
|
+
{ value: 'postgres', label: 'PostgreSQL' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Demonstrates that a multi-select dropdown menu renders correctly inside a
|
|
19
|
+
* `<Modal>`. By default `Select` portals its open menu to `document.body` so
|
|
20
|
+
* it escapes the modal's `overflow: hidden` clipping — meaning **the modal
|
|
21
|
+
* does NOT need to be sized large enough** to contain the menu. The menu
|
|
22
|
+
* uses `--crk-z-floating` (1060) which sits above `--crk-z-modal` (1050).
|
|
23
|
+
*
|
|
24
|
+
* Pair this pattern with `closeOnBackdrop={false}`: clicking the modal
|
|
25
|
+
* backdrop while the menu is open is "outside" the menu (closes the menu)
|
|
26
|
+
* AND on the backdrop (would close the modal too). Disabling backdrop
|
|
27
|
+
* dismissal scopes the click to closing only the menu — users dismiss the
|
|
28
|
+
* modal explicitly via Cancel/Save/×.
|
|
29
|
+
*
|
|
30
|
+
* If you have a reason to keep the menu inside the modal subtree (e.g.,
|
|
31
|
+
* parent-scoped CSS theming), pass `portal={false}` and size the modal
|
|
32
|
+
* generously.
|
|
33
|
+
*/
|
|
34
|
+
export function MultiSelectInModalRecipe() {
|
|
35
|
+
const [open, setOpen] = useState(false);
|
|
36
|
+
const [values, setValues] = useState<string[]>([]);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
<Button onClick={() => setOpen(true)}>Edit tags</Button>
|
|
41
|
+
<Modal open={open} onClose={() => setOpen(false)} size="sm" closeOnBackdrop={false}>
|
|
42
|
+
<Modal.Header onClose={() => setOpen(false)}>Tags</Modal.Header>
|
|
43
|
+
<Modal.Body>
|
|
44
|
+
<label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
|
45
|
+
<span style={{ fontSize: 12, color: 'var(--crk-color-text-muted)' }}>
|
|
46
|
+
Pick all that apply
|
|
47
|
+
</span>
|
|
48
|
+
<Select
|
|
49
|
+
multiple
|
|
50
|
+
options={TAGS}
|
|
51
|
+
value={values}
|
|
52
|
+
onValuesChange={setValues}
|
|
53
|
+
placeholder="Pick tags…"
|
|
54
|
+
/>
|
|
55
|
+
</label>
|
|
56
|
+
</Modal.Body>
|
|
57
|
+
<Modal.Footer>
|
|
58
|
+
<Button variant="ghost" onClick={() => setOpen(false)}>
|
|
59
|
+
Cancel
|
|
60
|
+
</Button>
|
|
61
|
+
<Button
|
|
62
|
+
variant="primary"
|
|
63
|
+
onClick={() => {
|
|
64
|
+
// ...persist values, then:
|
|
65
|
+
setOpen(false);
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
Save
|
|
69
|
+
</Button>
|
|
70
|
+
</Modal.Footer>
|
|
71
|
+
</Modal>
|
|
72
|
+
</>
|
|
73
|
+
);
|
|
74
|
+
}
|