acture-palette-react 1.0.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.
@@ -0,0 +1,135 @@
1
+ import { Registry, Context, Tier, AnyCommandRecord, Result, CommandKind } from 'acture';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * `<CommandPalette />` — Phase 2 implementation.
6
+ *
7
+ * Adds parameterized-command support per research-2 §9 (and the
8
+ * `acture-palette-design` skill):
9
+ *
10
+ * - `deriveKind(command)` returns 'atomic' | 'handoff'. Authors may
11
+ * override via `record.kind`.
12
+ * - 'atomic' commands render an inline picker chain INSIDE the
13
+ * palette (Linear / Discord chip-style).
14
+ * - 'handoff' commands either render a host-supplied form inline
15
+ * (when `formAdapter` is provided) or fall back to firing
16
+ * `onParameterizedSelect` for the host to open its own form view.
17
+ *
18
+ * Phase 1 behavior is preserved for parameter-free commands and for
19
+ * hosts that supply neither a form adapter nor a parameterized-select
20
+ * callback — the palette just closes the picker view.
21
+ *
22
+ * Per `acture-hard-donts` skill: no bundled UI kit. All elements use
23
+ * cmdk's built-in classes plus consumer-supplied className overrides.
24
+ */
25
+
26
+ type PaletteItemRenderer = (cmd: AnyCommandRecord) => React.ReactNode;
27
+ /** Props the palette passes to a host-supplied form adapter. The host
28
+ * renders a form derived from `command.params` and calls `onSubmit`
29
+ * with the validated params (or `onCancel`). */
30
+ interface PaletteFormAdapterProps {
31
+ command: AnyCommandRecord;
32
+ defaults?: Record<string, unknown>;
33
+ onSubmit: (params: unknown) => void;
34
+ onCancel: () => void;
35
+ }
36
+ type PaletteFormAdapter = React.ComponentType<PaletteFormAdapterProps>;
37
+ interface CommandPaletteProps {
38
+ /** The acture registry. */
39
+ registry: Registry;
40
+ /** Optional context for when-clause filtering and dispatch. */
41
+ context?: Context;
42
+ /** Tier filter. Default: `['stable']`. */
43
+ tiers?: readonly Tier[] | 'all';
44
+ /** Called when a dispatch (parameter-free OR parameterized) finishes. */
45
+ onDispatched?: (cmd: AnyCommandRecord, result: Result<unknown>) => void;
46
+ /** Fired when the user picks a `handoff` command and no `formAdapter`
47
+ * is configured. Hosts that want to open their own form view should
48
+ * handle this. */
49
+ onParameterizedSelect?: (cmd: AnyCommandRecord) => void;
50
+ /** Optional form adapter for `handoff` commands. When present, the
51
+ * palette switches its inner view to this component instead of
52
+ * closing. Plug in `acture-forms-autoform` or `acture-forms-rjsf`. */
53
+ formAdapter?: PaletteFormAdapter;
54
+ /** Per-field defaults injected into the picker chain / form. Useful
55
+ * for context-aware prefill (Things-style — research-2 §9.4). */
56
+ paramDefaults?: (cmd: AnyCommandRecord) => Record<string, unknown> | undefined;
57
+ placeholder?: string;
58
+ className?: string;
59
+ /** Custom item renderer for the list view. */
60
+ renderItem?: PaletteItemRenderer;
61
+ }
62
+ declare function CommandPalette(props: CommandPaletteProps): React.ReactElement;
63
+
64
+ /**
65
+ * Subscribe to a registry's `commandsChanged` event from inside React.
66
+ *
67
+ * Returns a monotonically-incrementing `revision` integer that changes
68
+ * whenever a command is added or removed. Useful as a key for
69
+ * `useMemo` over the command list.
70
+ */
71
+
72
+ declare function useCommandsChanged(registry: Registry): number;
73
+
74
+ /**
75
+ * Auto-derived `kind` heuristic per research-2 §9.3 (acture-palette-design
76
+ * skill). Determines whether a parameterized command should be collected
77
+ * inline (atomic picker chain) or handed off to a dedicated form.
78
+ *
79
+ * 0 params → atomic
80
+ * 1–2 params, all picker-typed → atomic
81
+ * 3 params, all picker-typed AND all have defaults → atomic
82
+ * else → handoff
83
+ *
84
+ * "Picker-typed" = the param has a discrete, enumerable value space
85
+ * (enum, boolean) OR is a string carrying an explicit `paramKind: 'picker'`
86
+ * extension hint via `.describe()`. Unconstrained `z.string()` and
87
+ * `z.number()` are NOT picker-typed.
88
+ *
89
+ * Authors override by setting `kind` explicitly on the CommandRecord.
90
+ */
91
+
92
+ interface ParamSummary {
93
+ readonly name: string;
94
+ readonly schema: z.ZodTypeAny;
95
+ readonly isPicker: boolean;
96
+ readonly hasDefault: boolean;
97
+ readonly optional: boolean;
98
+ }
99
+ /** Inspect a Zod schema and produce per-field summaries for deriveKind
100
+ * and the picker-chain renderer. Defensive against non-object schemas. */
101
+ declare function summarizeParams(record: AnyCommandRecord): ParamSummary[];
102
+ /** Auto-derive `kind` from the param summary; explicit `kind` wins. */
103
+ declare function deriveKind(record: AnyCommandRecord): CommandKind;
104
+ /** Picker-typed = discrete, enumerable value space. */
105
+ declare function isPickerSchema(s: z.ZodTypeAny): boolean;
106
+ /** Read enum options for picker rendering. Returns [] for non-enums. */
107
+ declare function readEnumOptions(s: z.ZodTypeAny): string[];
108
+
109
+ /**
110
+ * Atomic picker-chain UI rendered INSIDE the palette container.
111
+ *
112
+ * Used when `deriveKind(record) === 'atomic'` for parameterized
113
+ * commands. Each step shows a labeled picker / input for one param;
114
+ * Enter advances when valid; Esc backs up to the previous step (or
115
+ * cancels at step 0).
116
+ *
117
+ * Per research-2 §9.4: per-step validation inline, step counter `n/N`
118
+ * only when N ≥ 2, Tab/Enter both advance, Esc backs up.
119
+ *
120
+ * This is deliberately minimal — a host that wants richer field
121
+ * widgets can pass a custom `pickerRenderer`.
122
+ */
123
+
124
+ interface PickerChainProps {
125
+ command: AnyCommandRecord;
126
+ /** Initial values (e.g. defaults derived from context). */
127
+ defaults?: Record<string, unknown>;
128
+ /** Called when the user finishes the last step. */
129
+ onSubmit: (params: Record<string, unknown>) => void;
130
+ /** Called when the user cancels (Esc at step 0). */
131
+ onCancel: () => void;
132
+ }
133
+ declare function PickerChain(props: PickerChainProps): React.ReactElement;
134
+
135
+ export { CommandPalette, type CommandPaletteProps, type PaletteFormAdapter, type PaletteFormAdapterProps, type PaletteItemRenderer, type ParamSummary, PickerChain, type PickerChainProps, deriveKind, isPickerSchema, readEnumOptions, summarizeParams, useCommandsChanged };
@@ -0,0 +1,135 @@
1
+ import { Registry, Context, Tier, AnyCommandRecord, Result, CommandKind } from 'acture';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * `<CommandPalette />` — Phase 2 implementation.
6
+ *
7
+ * Adds parameterized-command support per research-2 §9 (and the
8
+ * `acture-palette-design` skill):
9
+ *
10
+ * - `deriveKind(command)` returns 'atomic' | 'handoff'. Authors may
11
+ * override via `record.kind`.
12
+ * - 'atomic' commands render an inline picker chain INSIDE the
13
+ * palette (Linear / Discord chip-style).
14
+ * - 'handoff' commands either render a host-supplied form inline
15
+ * (when `formAdapter` is provided) or fall back to firing
16
+ * `onParameterizedSelect` for the host to open its own form view.
17
+ *
18
+ * Phase 1 behavior is preserved for parameter-free commands and for
19
+ * hosts that supply neither a form adapter nor a parameterized-select
20
+ * callback — the palette just closes the picker view.
21
+ *
22
+ * Per `acture-hard-donts` skill: no bundled UI kit. All elements use
23
+ * cmdk's built-in classes plus consumer-supplied className overrides.
24
+ */
25
+
26
+ type PaletteItemRenderer = (cmd: AnyCommandRecord) => React.ReactNode;
27
+ /** Props the palette passes to a host-supplied form adapter. The host
28
+ * renders a form derived from `command.params` and calls `onSubmit`
29
+ * with the validated params (or `onCancel`). */
30
+ interface PaletteFormAdapterProps {
31
+ command: AnyCommandRecord;
32
+ defaults?: Record<string, unknown>;
33
+ onSubmit: (params: unknown) => void;
34
+ onCancel: () => void;
35
+ }
36
+ type PaletteFormAdapter = React.ComponentType<PaletteFormAdapterProps>;
37
+ interface CommandPaletteProps {
38
+ /** The acture registry. */
39
+ registry: Registry;
40
+ /** Optional context for when-clause filtering and dispatch. */
41
+ context?: Context;
42
+ /** Tier filter. Default: `['stable']`. */
43
+ tiers?: readonly Tier[] | 'all';
44
+ /** Called when a dispatch (parameter-free OR parameterized) finishes. */
45
+ onDispatched?: (cmd: AnyCommandRecord, result: Result<unknown>) => void;
46
+ /** Fired when the user picks a `handoff` command and no `formAdapter`
47
+ * is configured. Hosts that want to open their own form view should
48
+ * handle this. */
49
+ onParameterizedSelect?: (cmd: AnyCommandRecord) => void;
50
+ /** Optional form adapter for `handoff` commands. When present, the
51
+ * palette switches its inner view to this component instead of
52
+ * closing. Plug in `acture-forms-autoform` or `acture-forms-rjsf`. */
53
+ formAdapter?: PaletteFormAdapter;
54
+ /** Per-field defaults injected into the picker chain / form. Useful
55
+ * for context-aware prefill (Things-style — research-2 §9.4). */
56
+ paramDefaults?: (cmd: AnyCommandRecord) => Record<string, unknown> | undefined;
57
+ placeholder?: string;
58
+ className?: string;
59
+ /** Custom item renderer for the list view. */
60
+ renderItem?: PaletteItemRenderer;
61
+ }
62
+ declare function CommandPalette(props: CommandPaletteProps): React.ReactElement;
63
+
64
+ /**
65
+ * Subscribe to a registry's `commandsChanged` event from inside React.
66
+ *
67
+ * Returns a monotonically-incrementing `revision` integer that changes
68
+ * whenever a command is added or removed. Useful as a key for
69
+ * `useMemo` over the command list.
70
+ */
71
+
72
+ declare function useCommandsChanged(registry: Registry): number;
73
+
74
+ /**
75
+ * Auto-derived `kind` heuristic per research-2 §9.3 (acture-palette-design
76
+ * skill). Determines whether a parameterized command should be collected
77
+ * inline (atomic picker chain) or handed off to a dedicated form.
78
+ *
79
+ * 0 params → atomic
80
+ * 1–2 params, all picker-typed → atomic
81
+ * 3 params, all picker-typed AND all have defaults → atomic
82
+ * else → handoff
83
+ *
84
+ * "Picker-typed" = the param has a discrete, enumerable value space
85
+ * (enum, boolean) OR is a string carrying an explicit `paramKind: 'picker'`
86
+ * extension hint via `.describe()`. Unconstrained `z.string()` and
87
+ * `z.number()` are NOT picker-typed.
88
+ *
89
+ * Authors override by setting `kind` explicitly on the CommandRecord.
90
+ */
91
+
92
+ interface ParamSummary {
93
+ readonly name: string;
94
+ readonly schema: z.ZodTypeAny;
95
+ readonly isPicker: boolean;
96
+ readonly hasDefault: boolean;
97
+ readonly optional: boolean;
98
+ }
99
+ /** Inspect a Zod schema and produce per-field summaries for deriveKind
100
+ * and the picker-chain renderer. Defensive against non-object schemas. */
101
+ declare function summarizeParams(record: AnyCommandRecord): ParamSummary[];
102
+ /** Auto-derive `kind` from the param summary; explicit `kind` wins. */
103
+ declare function deriveKind(record: AnyCommandRecord): CommandKind;
104
+ /** Picker-typed = discrete, enumerable value space. */
105
+ declare function isPickerSchema(s: z.ZodTypeAny): boolean;
106
+ /** Read enum options for picker rendering. Returns [] for non-enums. */
107
+ declare function readEnumOptions(s: z.ZodTypeAny): string[];
108
+
109
+ /**
110
+ * Atomic picker-chain UI rendered INSIDE the palette container.
111
+ *
112
+ * Used when `deriveKind(record) === 'atomic'` for parameterized
113
+ * commands. Each step shows a labeled picker / input for one param;
114
+ * Enter advances when valid; Esc backs up to the previous step (or
115
+ * cancels at step 0).
116
+ *
117
+ * Per research-2 §9.4: per-step validation inline, step counter `n/N`
118
+ * only when N ≥ 2, Tab/Enter both advance, Esc backs up.
119
+ *
120
+ * This is deliberately minimal — a host that wants richer field
121
+ * widgets can pass a custom `pickerRenderer`.
122
+ */
123
+
124
+ interface PickerChainProps {
125
+ command: AnyCommandRecord;
126
+ /** Initial values (e.g. defaults derived from context). */
127
+ defaults?: Record<string, unknown>;
128
+ /** Called when the user finishes the last step. */
129
+ onSubmit: (params: Record<string, unknown>) => void;
130
+ /** Called when the user cancels (Esc at step 0). */
131
+ onCancel: () => void;
132
+ }
133
+ declare function PickerChain(props: PickerChainProps): React.ReactElement;
134
+
135
+ export { CommandPalette, type CommandPaletteProps, type PaletteFormAdapter, type PaletteFormAdapterProps, type PaletteItemRenderer, type ParamSummary, PickerChain, type PickerChainProps, deriveKind, isPickerSchema, readEnumOptions, summarizeParams, useCommandsChanged };