@darthcharles/greda 1.2.0 → 1.3.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/README.md CHANGED
@@ -45,6 +45,45 @@ Greda and application markup share unprefixed utility classes such as
45
45
  `className` to override component defaults. See the introduction guide for supported
46
46
  utilities and migration from `ds-*` classes.
47
47
 
48
+ ## Searchable selection
49
+
50
+ Use `Combobox` for filtering as you type and optional option creation. It uses
51
+ existing Radix dependencies. `Select` remains available for simple selection.
52
+
53
+ Import the same package stylesheet shown in Quick start, then compose the field:
54
+
55
+ ```tsx
56
+ import {
57
+ Combobox, ComboboxInput, ComboboxContent, Label,
58
+ } from "@darthcharles/greda";
59
+
60
+ const materials = [
61
+ { value: "clay", label: "Clay", keywords: ["pottery"] },
62
+ { value: "linen", label: "Linen" },
63
+ ];
64
+
65
+ export function MaterialField() {
66
+ return (
67
+ <>
68
+ <Label htmlFor="material">Material</Label>
69
+ <Combobox
70
+ options={materials}
71
+ name="material"
72
+ onCreate={(label) => ({ value: crypto.randomUUID(), label })}
73
+ >
74
+ <ComboboxInput id="material" placeholder="Choose or create" required />
75
+ <ComboboxContent />
76
+ </Combobox>
77
+ </>
78
+ );
79
+ }
80
+ ```
81
+
82
+ See the [usage guide](src/stories/Combobox.mdx) for controlled state, remote
83
+ search, creation callbacks, forms, and keyboard interaction. Explore the
84
+ [Storybook examples](https://elegant-hotteok-cbb834.netlify.app/?path=/docs/components-combobox--docs)
85
+ for component states.
86
+
48
87
  ## With Tailwind 4
49
88
 
50
89
  Import Greda's tokens in your app's Tailwind CSS entry point. This registers the
@@ -108,7 +147,7 @@ element. Importing it alone leaves the neutral base unchanged. The application
108
147
  still controls page backgrounds and fonts. Select **cobalto** in Storybook to
109
148
  preview components, and see the [composition recipe](src/stories/Cobalto.mdx)
110
149
  for large mixed-weight titles, an asterisk, a polaroid photo, scoped portals,
111
- and Tailwind 4 import order. Both recipes use Tailwind utilities directly in JSX;
150
+ and Tailwind 4 import order. The recipes use Tailwind utilities directly in JSX;
112
151
  compile them with your application’s Tailwind 4 setup.
113
152
 
114
153
  Comal is also available as an optional theme. Import
@@ -117,10 +156,18 @@ Comal is also available as an optional theme. Import
117
156
  element. It uses warm neutrals, terracotta actions and rounded corners. Its font
118
157
  stacks reference DM Sans and Fraunces; load those fonts in your application or
119
158
  override `--font-sans` and `--font-heading`. No fonts are downloaded or bundled
120
- by either theme. Both exports can be imported together and selected by attribute.
159
+ by these themes. Theme exports can be imported together and selected by attribute.
121
160
  See the [Comal composition recipe](src/stories/Comal.mdx) for a complete fictional
122
161
  workshop page, optional font setup, responsive layout and copyable Tailwind JSX.
123
162
 
163
+ Matrix adds a terminal identity with green actions, system monospace fonts and
164
+ square controls. Import `@darthcharles/greda/themes/matrix.css` after the package
165
+ stylesheet and set `data-theme="matrix"` with `data-color-scheme="dark"` for
166
+ green-black surfaces, or `"light"` for pale green surfaces. No font setup is
167
+ required. Select **matrix** in Storybook to preview components, or see the
168
+ [Matrix composition recipe](src/stories/Matrix.mdx) for a responsive console
169
+ layout and Tailwind 4 setup.
170
+
124
171
  Customization is optional. To change the default theme, import your own
125
172
  `theme.css` after the package stylesheet and override the base colors or other
126
173
  tokens you need.
@@ -0,0 +1,48 @@
1
+ import * as React from "react";
2
+ import { Input } from "./input";
3
+ import { type PopoverContentProps } from "./popover";
4
+ export interface ComboboxOption {
5
+ /** Stable, unique ID used for selection and form submission. */
6
+ value: string;
7
+ label: string;
8
+ disabled?: boolean;
9
+ keywords?: string[];
10
+ }
11
+ export type ComboboxFilter = (option: ComboboxOption, query: string) => boolean;
12
+ export interface ComboboxProps {
13
+ children: React.ReactNode;
14
+ options: ComboboxOption[];
15
+ value?: ComboboxOption | null;
16
+ defaultValue?: ComboboxOption | null;
17
+ onValueChange?: (option: ComboboxOption | null) => void;
18
+ inputValue?: string;
19
+ defaultInputValue?: string;
20
+ onInputValueChange?: (query: string) => void;
21
+ open?: boolean;
22
+ defaultOpen?: boolean;
23
+ onOpenChange?: (open: boolean) => void;
24
+ /** false preserves remote results and their ordering without filtering again. */
25
+ filter?: ComboboxFilter | false;
26
+ loading?: boolean;
27
+ error?: React.ReactNode;
28
+ disabled?: boolean;
29
+ name?: string;
30
+ form?: string;
31
+ onCreate?: (query: string) => ComboboxOption | Promise<ComboboxOption>;
32
+ /** Additional eligibility check; the server must still enforce uniqueness. */
33
+ isValidNewOption?: (query: string, options: ComboboxOption[]) => boolean;
34
+ }
35
+ declare function Combobox({ children, options, value, defaultValue, onValueChange, inputValue, defaultInputValue, onInputValueChange, open: controlledOpen, defaultOpen, onOpenChange, filter, loading, error, disabled, name, form, onCreate, isValidNewOption, }: ComboboxProps): React.JSX.Element;
36
+ export type ComboboxInputProps = Omit<React.ComponentPropsWithoutRef<typeof Input>, "value" | "defaultValue" | "type" | "role" | "name" | "disabled">;
37
+ declare const ComboboxInput: React.ForwardRefExoticComponent<ComboboxInputProps & React.RefAttributes<HTMLInputElement>>;
38
+ export interface ComboboxContentProps extends Omit<PopoverContentProps, "children" | "role"> {
39
+ emptyText?: React.ReactNode;
40
+ loadingText?: React.ReactNode;
41
+ creatingText?: React.ReactNode;
42
+ createErrorText?: React.ReactNode;
43
+ renderCreateLabel?: (query: string) => React.ReactNode;
44
+ renderOption?: (option: ComboboxOption) => React.ReactNode;
45
+ getStatusText?: (count: number, canCreate: boolean) => string;
46
+ }
47
+ declare const ComboboxContent: React.ForwardRefExoticComponent<ComboboxContentProps & React.RefAttributes<HTMLDivElement>>;
48
+ export { Combobox, ComboboxInput, ComboboxContent };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./components/ui/input";
3
3
  export * from "./components/ui/textarea";
4
4
  export * from "./components/ui/label";
5
5
  export * from "./components/ui/select";
6
+ export * from "./components/ui/combobox";
6
7
  export * from "./components/ui/dialog";
7
8
  export * from "./components/ui/card";
8
9
  export * from "./components/ui/badge";