@philosaether/chipper 0.1.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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +778 -0
  3. package/dist/base.css +1 -0
  4. package/dist/headless.d.ts +16 -0
  5. package/dist/headless.d.ts.map +1 -0
  6. package/dist/headless.js +18 -0
  7. package/dist/index.js +1445 -0
  8. package/dist/src/builder/index.d.ts +82 -0
  9. package/dist/src/builder/index.d.ts.map +1 -0
  10. package/dist/src/builder/predicates.d.ts +18 -0
  11. package/dist/src/builder/predicates.d.ts.map +1 -0
  12. package/dist/src/components/Chip.d.ts +15 -0
  13. package/dist/src/components/Chip.d.ts.map +1 -0
  14. package/dist/src/components/ChipInfoPopup.d.ts +12 -0
  15. package/dist/src/components/ChipInfoPopup.d.ts.map +1 -0
  16. package/dist/src/components/ChipPopup.d.ts +20 -0
  17. package/dist/src/components/ChipPopup.d.ts.map +1 -0
  18. package/dist/src/components/Chipper.d.ts +25 -0
  19. package/dist/src/components/Chipper.d.ts.map +1 -0
  20. package/dist/src/components/Clause.d.ts +13 -0
  21. package/dist/src/components/Clause.d.ts.map +1 -0
  22. package/dist/src/components/Sentence.d.ts +15 -0
  23. package/dist/src/components/Sentence.d.ts.map +1 -0
  24. package/dist/src/components/index.d.ts +12 -0
  25. package/dist/src/components/index.d.ts.map +1 -0
  26. package/dist/src/components/popups/AlternativeCoordinatePopup.d.ts +16 -0
  27. package/dist/src/components/popups/AlternativeCoordinatePopup.d.ts.map +1 -0
  28. package/dist/src/components/popups/KeywordGroupList.d.ts +29 -0
  29. package/dist/src/components/popups/KeywordGroupList.d.ts.map +1 -0
  30. package/dist/src/components/popups/KeywordOrExpressionPopup.d.ts +30 -0
  31. package/dist/src/components/popups/KeywordOrExpressionPopup.d.ts.map +1 -0
  32. package/dist/src/components/popups/MultiSelectPopup.d.ts +20 -0
  33. package/dist/src/components/popups/MultiSelectPopup.d.ts.map +1 -0
  34. package/dist/src/components/popups/NumericInput.d.ts +16 -0
  35. package/dist/src/components/popups/NumericInput.d.ts.map +1 -0
  36. package/dist/src/components/popups/ReferencePopup.d.ts +20 -0
  37. package/dist/src/components/popups/ReferencePopup.d.ts.map +1 -0
  38. package/dist/src/core/actions/set-chip-value.d.ts +17 -0
  39. package/dist/src/core/actions/set-chip-value.d.ts.map +1 -0
  40. package/dist/src/core/actions/set-context.d.ts +18 -0
  41. package/dist/src/core/actions/set-context.d.ts.map +1 -0
  42. package/dist/src/core/actions/set-display-value.d.ts +18 -0
  43. package/dist/src/core/actions/set-display-value.d.ts.map +1 -0
  44. package/dist/src/core/actions/toggle-clause.d.ts +15 -0
  45. package/dist/src/core/actions/toggle-clause.d.ts.map +1 -0
  46. package/dist/src/core/context-resolution.d.ts +36 -0
  47. package/dist/src/core/context-resolution.d.ts.map +1 -0
  48. package/dist/src/core/initialize.d.ts +43 -0
  49. package/dist/src/core/initialize.d.ts.map +1 -0
  50. package/dist/src/core/mode-switching.d.ts +10 -0
  51. package/dist/src/core/mode-switching.d.ts.map +1 -0
  52. package/dist/src/core/reducer.d.ts +16 -0
  53. package/dist/src/core/reducer.d.ts.map +1 -0
  54. package/dist/src/core/resolve-keyword-label.d.ts +7 -0
  55. package/dist/src/core/resolve-keyword-label.d.ts.map +1 -0
  56. package/dist/src/core/serialize.d.ts +34 -0
  57. package/dist/src/core/serialize.d.ts.map +1 -0
  58. package/dist/src/core/state.d.ts +59 -0
  59. package/dist/src/core/state.d.ts.map +1 -0
  60. package/dist/src/core/store.d.ts +23 -0
  61. package/dist/src/core/store.d.ts.map +1 -0
  62. package/dist/src/core/types.d.ts +242 -0
  63. package/dist/src/core/types.d.ts.map +1 -0
  64. package/dist/src/domains/alternative-coordinate.d.ts +110 -0
  65. package/dist/src/domains/alternative-coordinate.d.ts.map +1 -0
  66. package/dist/src/domains/create-domain.d.ts +30 -0
  67. package/dist/src/domains/create-domain.d.ts.map +1 -0
  68. package/dist/src/domains/facades.d.ts +134 -0
  69. package/dist/src/domains/facades.d.ts.map +1 -0
  70. package/dist/src/domains/index.d.ts +14 -0
  71. package/dist/src/domains/index.d.ts.map +1 -0
  72. package/dist/src/domains/keyword-or-expression.d.ts +148 -0
  73. package/dist/src/domains/keyword-or-expression.d.ts.map +1 -0
  74. package/dist/src/domains/multi-select.d.ts +68 -0
  75. package/dist/src/domains/multi-select.d.ts.map +1 -0
  76. package/dist/src/domains/normalize-keywords.d.ts +83 -0
  77. package/dist/src/domains/normalize-keywords.d.ts.map +1 -0
  78. package/dist/src/domains/reference.d.ts +89 -0
  79. package/dist/src/domains/reference.d.ts.map +1 -0
  80. package/dist/src/hooks/SentenceProvider.d.ts +17 -0
  81. package/dist/src/hooks/SentenceProvider.d.ts.map +1 -0
  82. package/dist/src/hooks/context.d.ts +31 -0
  83. package/dist/src/hooks/context.d.ts.map +1 -0
  84. package/dist/src/hooks/index.d.ts +13 -0
  85. package/dist/src/hooks/index.d.ts.map +1 -0
  86. package/dist/src/hooks/useChip.d.ts +21 -0
  87. package/dist/src/hooks/useChip.d.ts.map +1 -0
  88. package/dist/src/hooks/useDisplaySource.d.ts +16 -0
  89. package/dist/src/hooks/useDisplaySource.d.ts.map +1 -0
  90. package/dist/src/hooks/useKeyboardNavigation.d.ts +44 -0
  91. package/dist/src/hooks/useKeyboardNavigation.d.ts.map +1 -0
  92. package/dist/src/hooks/usePopup.d.ts +13 -0
  93. package/dist/src/hooks/usePopup.d.ts.map +1 -0
  94. package/dist/src/hooks/useReferenceDisplay.d.ts +22 -0
  95. package/dist/src/hooks/useReferenceDisplay.d.ts.map +1 -0
  96. package/dist/src/hooks/useSentence.d.ts +14 -0
  97. package/dist/src/hooks/useSentence.d.ts.map +1 -0
  98. package/dist/src/index.d.ts +25 -0
  99. package/dist/src/index.d.ts.map +1 -0
  100. package/dist/src/palette/index.d.ts +29 -0
  101. package/dist/src/palette/index.d.ts.map +1 -0
  102. package/dist/src/themes/apply-theme.d.ts +34 -0
  103. package/dist/src/themes/apply-theme.d.ts.map +1 -0
  104. package/dist/src/themes/create-hue.d.ts +23 -0
  105. package/dist/src/themes/create-hue.d.ts.map +1 -0
  106. package/dist/src/themes/index.d.ts +13 -0
  107. package/dist/src/themes/index.d.ts.map +1 -0
  108. package/dist/src/themes/midnight.d.ts +11 -0
  109. package/dist/src/themes/midnight.d.ts.map +1 -0
  110. package/dist/src/themes/praxis.d.ts +11 -0
  111. package/dist/src/themes/praxis.d.ts.map +1 -0
  112. package/dist/src/themes/terminal.d.ts +9 -0
  113. package/dist/src/themes/terminal.d.ts.map +1 -0
  114. package/dist/src/themes/types.d.ts +72 -0
  115. package/dist/src/themes/types.d.ts.map +1 -0
  116. package/dist/styles.css +1 -0
  117. package/dist/themes/index.js +256 -0
  118. package/dist/themes/midnight.css +1 -0
  119. package/dist/themes/praxis.css +1 -0
  120. package/dist/themes/terminal.css +1 -0
  121. package/dist/usePopup-Of6OHa1_.js +653 -0
  122. package/package.json +75 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Facade domain factories — sugar over keywordOrExpressionDomain.
3
+ *
4
+ * These hide KOE internals for the most common chip types. Consumers
5
+ * define text inputs, number inputs, date pickers, and keyword lists
6
+ * without thinking about expression modes or input types.
7
+ *
8
+ * See koe-facades.md.
9
+ */
10
+ import type { Domain, SentenceContext } from '../core/types';
11
+ import type { KeywordGroupItem } from './normalize-keywords';
12
+ /** Configuration for a free-text domain. */
13
+ export interface TextDomainConfig {
14
+ /** Semantic color key */
15
+ color: string;
16
+ /** Text shown in chip trigger when empty */
17
+ placeholder?: string;
18
+ /** Initial value (defaults to '' → shows placeholder) */
19
+ default?: string;
20
+ /** Character limit (default 140) */
21
+ maxLength?: number;
22
+ /** Custom validation beyond non-empty */
23
+ validate?: (value: string) => boolean;
24
+ /** Format value for chip trigger display */
25
+ display?: (value: string) => string;
26
+ /** Optional preset values as keyword pills. Accepts groups for visual grouping. */
27
+ keywords?: KeywordGroupItem<string>[];
28
+ }
29
+ /**
30
+ * Create a free-text domain. The simplest freeform chip.
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const taskName = textDomain({
35
+ * color: 'rose',
36
+ * placeholder: 'a task name',
37
+ * });
38
+ * ```
39
+ */
40
+ export declare function textDomain(config: TextDomainConfig): Domain<string>;
41
+ /** Configuration for a numeric domain. */
42
+ export interface NumberDomainConfig {
43
+ /** Semantic color key */
44
+ color: string;
45
+ /** Text shown in chip trigger when empty */
46
+ placeholder?: string;
47
+ /** Initial value (defaults to '' → shows placeholder) */
48
+ default?: string;
49
+ /** Minimum value */
50
+ min?: number;
51
+ /** Maximum value */
52
+ max?: number;
53
+ /** Step increment for +/- buttons (default 1) */
54
+ step?: number;
55
+ /** Text before the input (static or context-aware) */
56
+ prefix?: string | ((ctx: SentenceContext) => string);
57
+ /** Text after the input (static or context-aware) */
58
+ suffix?: string | ((ctx: SentenceContext) => string);
59
+ /** Custom validation beyond numeric check */
60
+ validate?: (value: string) => boolean;
61
+ /** Format value for chip trigger display */
62
+ display?: (value: string) => string;
63
+ /** Optional preset values as keyword pills. Accepts groups for visual grouping. */
64
+ keywords?: KeywordGroupItem<string>[];
65
+ }
66
+ /**
67
+ * Create a numeric domain with stepper UI.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const interval = numberDomain({
72
+ * color: 'copper',
73
+ * min: 1,
74
+ * max: 365,
75
+ * placeholder: 'an interval',
76
+ * });
77
+ * ```
78
+ */
79
+ export declare function numberDomain(config: NumberDomainConfig): Domain<string>;
80
+ /** Configuration for a calendar date domain. */
81
+ export interface DateDomainConfig {
82
+ /** Semantic color key */
83
+ color: string;
84
+ /** Text shown in chip trigger when empty */
85
+ placeholder?: string;
86
+ /** Initial value (defaults to '' → shows placeholder) */
87
+ default?: string;
88
+ /** Custom validation beyond YYYY-MM-DD format */
89
+ validate?: (value: string) => boolean;
90
+ /** Format date for chip trigger display */
91
+ display?: (value: string) => string;
92
+ /** Optional preset values (e.g., "tomorrow", "next Monday"). Accepts groups for visual grouping. */
93
+ keywords?: KeywordGroupItem<string>[];
94
+ }
95
+ /**
96
+ * Create a calendar date picker domain.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const dueDate = dateDomain({
101
+ * color: 'sage',
102
+ * placeholder: 'a date',
103
+ * });
104
+ * ```
105
+ */
106
+ export declare function dateDomain(config: DateDomainConfig): Domain<string>;
107
+ /** Configuration for a keywords-only domain. */
108
+ export interface KeywordDomainConfig {
109
+ /** Semantic color key */
110
+ color: string;
111
+ /** The complete set of allowed values. Accepts groups for visual grouping. */
112
+ keywords: KeywordGroupItem<string>[];
113
+ /** Default value (defaults to first keyword value) */
114
+ default?: string;
115
+ /** Text shown in chip trigger when value is invalid */
116
+ placeholder?: string;
117
+ }
118
+ /**
119
+ * Create a keywords-only domain. Replaces enumDomain.
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const priority = keywordDomain({
124
+ * color: 'rose',
125
+ * keywords: [
126
+ * { value: 'low' },
127
+ * { value: 'medium' },
128
+ * { value: 'high' },
129
+ * ],
130
+ * });
131
+ * ```
132
+ */
133
+ export declare function keywordDomain(config: KeywordDomainConfig): Domain<string>;
134
+ //# sourceMappingURL=facades.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facades.d.ts","sourceRoot":"","sources":["../../../src/domains/facades.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Domain archetype implementations.
3
+ *
4
+ * Each archetype provides a factory function that creates a configured
5
+ * Domain instance. See chipper-architecture.md §2, domain-factories.md,
6
+ * koe-facades.md.
7
+ */
8
+ export { keywordOrExpressionDomain, expressionDomain, textExpression, numericExpression, dateExpression, type KeywordOrExpressionDomainConfig, type ExpressionDomainConfig, type ExpressionConfig, type ExpressionTrigger, } from './keyword-or-expression';
9
+ export { type KeywordConfig, type KeywordGroup, type KeywordGroupItem, type NormalizedKeywordGroup, } from './normalize-keywords';
10
+ export { textDomain, numberDomain, dateDomain, keywordDomain, type TextDomainConfig, type NumberDomainConfig, type DateDomainConfig, type KeywordDomainConfig, } from './facades';
11
+ export { multiSelectDomain, selectionMatchesKeyword, type MultiSelectDomainConfig, } from './multi-select';
12
+ export { alternativeCoordinateDomain, type AlternativeCoordinateDomainConfig, type AlternativeCoordinateMode, type ResolvedAlternativeCoordinateMode, type ResolvedModeSlot, type ModeSlot, } from './alternative-coordinate';
13
+ export { referenceDomain, type ReferenceDomainConfig, type ReferenceSource, type ReferenceItem, } from './reference';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domains/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,KAAK,+BAA+B,EACpC,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,2BAA2B,EAC3B,KAAK,iCAAiC,EACtC,KAAK,yBAAyB,EAC9B,KAAK,iCAAiC,EACtC,KAAK,gBAAgB,EACrB,KAAK,QAAQ,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Keyword-or-expression domain — keywords for common values, text input
3
+ * for everything else.
4
+ *
5
+ * The second archetype. Covers time, due, task name, description, number,
6
+ * start, collate name — any domain where the value space is "a few presets
7
+ * plus freeform."
8
+ *
9
+ * Also exports expressionDomain as a convenience alias for expression-only
10
+ * domains (no keywords).
11
+ */
12
+ import type { Domain, Keyword, SentenceContext } from '../core/types';
13
+ import { type KeywordGroupItem } from './normalize-keywords';
14
+ /** Configuration for a trigger keyword that enters expression mode. */
15
+ export interface ExpressionTrigger {
16
+ /** Popup pill label (e.g., "custom interval") */
17
+ label: string;
18
+ /** Default value when entering expression mode (e.g., "2") */
19
+ default: string;
20
+ }
21
+ /** Expression mode configuration for the text input. */
22
+ export interface ExpressionConfig {
23
+ /** Input type — 'text', 'number' (stepper UI), or 'date' (calendar picker). Required. */
24
+ inputType: 'text' | 'number' | 'date';
25
+ /** Placeholder text for the input field */
26
+ placeholder?: string;
27
+ /** Maximum character length (omit for unlimited, text only) */
28
+ maxLength?: number;
29
+ /** Minimum value (number inputs only) */
30
+ min?: number;
31
+ /** Maximum value (number inputs only) */
32
+ max?: number;
33
+ /** Step increment for +/- buttons (number inputs only, default 1) */
34
+ step?: number;
35
+ /** Validate typed input (beyond non-empty). Return true if valid. */
36
+ validate?: (value: string) => boolean;
37
+ /** Format the value for chip trigger display (default: identity) */
38
+ display?: (value: string) => string;
39
+ /** Text shown before the input in the popup (e.g., "in"). Function receives sentence context. */
40
+ prefix?: string | ((context: Record<string, unknown>) => string);
41
+ /** Text shown after the input in the popup (e.g., "months"). Function receives sentence context. */
42
+ suffix?: string | ((context: Record<string, unknown>) => string);
43
+ /** Expression input placement relative to keywords: 'above' or 'below' (default 'below'). */
44
+ position?: 'above' | 'below';
45
+ /**
46
+ * Keyword that enters expression mode when selected.
47
+ * When absent, the expression input is always visible in the popup.
48
+ * When present, the expression input is hidden until this trigger is selected.
49
+ */
50
+ trigger?: ExpressionTrigger;
51
+ }
52
+ /**
53
+ * Create a text expression config.
54
+ * Sugar for { inputType: 'text', ...options }.
55
+ */
56
+ export declare function textExpression(options?: Omit<ExpressionConfig, 'inputType'>): ExpressionConfig;
57
+ /**
58
+ * Create a numeric expression config.
59
+ * Sugar for { inputType: 'number', ...options } with sensible defaults.
60
+ */
61
+ export declare function numericExpression(options?: Omit<ExpressionConfig, 'inputType'>): ExpressionConfig;
62
+ /**
63
+ * Create a calendar date expression config.
64
+ * Sugar for { inputType: 'date', ...options } with sensible defaults.
65
+ * Values are YYYY-MM-DD strings (native date input format).
66
+ */
67
+ export declare function dateExpression(options?: Omit<ExpressionConfig, 'inputType'>): ExpressionConfig;
68
+ /** Configuration for a keyword-or-expression domain. */
69
+ export interface KeywordOrExpressionDomainConfig {
70
+ /** Semantic color key */
71
+ color: string;
72
+ /** Preset values shown as keyword pills in the popup. Accepts groups for visual grouping. */
73
+ keywords?: KeywordGroupItem<string>[] | Keyword<string>[];
74
+ /** Expression mode configuration. Omit for keywords-only domains. */
75
+ expression?: ExpressionConfig;
76
+ /** Default value. When omitted, uses first keyword's value or '' if no keywords. */
77
+ default?: string;
78
+ /** @deprecated Use `default` instead */
79
+ defaultValue?: string;
80
+ /** Text shown in chip trigger when value is invalid */
81
+ placeholder?: string;
82
+ /** Context keys this domain reads from ancestor producers */
83
+ consumes?: string[];
84
+ /** Context keys this domain writes for descendant consumers */
85
+ produces?: string[];
86
+ /** Reconfigure domain when ancestor context changes */
87
+ onContextChange?: (context: SentenceContext) => Partial<Domain<string>>;
88
+ }
89
+ /**
90
+ * Create a keyword-or-expression domain.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const timeOfDay = keywordOrExpressionDomain({
95
+ * color: 'copper',
96
+ * keywords: [
97
+ * { value: '09:00', label: 'morning' },
98
+ * { value: '12:00', label: 'afternoon' },
99
+ * { value: '17:00', label: 'evening' },
100
+ * ],
101
+ * expression: textExpression({
102
+ * placeholder: 'a specific time (HH:MM)',
103
+ * validate: (v) => /^\d{2}:\d{2}$/.test(v),
104
+ * }),
105
+ * placeholder: 'a time',
106
+ * });
107
+ * ```
108
+ */
109
+ export declare function keywordOrExpressionDomain(config: KeywordOrExpressionDomainConfig): Domain<string>;
110
+ /** Configuration for an expression-only domain (no keywords). */
111
+ export interface ExpressionDomainConfig {
112
+ /** Semantic color key */
113
+ color: string;
114
+ /** Expression mode configuration */
115
+ expression: ExpressionConfig;
116
+ /** Default value. Empty string if omitted (invalid → placeholder). */
117
+ default?: string;
118
+ /** @deprecated Use `default` instead */
119
+ defaultValue?: string;
120
+ /** Text shown in chip trigger when value is invalid */
121
+ placeholder?: string;
122
+ /** Context keys this domain reads from ancestor producers */
123
+ consumes?: string[];
124
+ /** Context keys this domain writes for descendant consumers */
125
+ produces?: string[];
126
+ /** Reconfigure domain when ancestor context changes */
127
+ onContextChange?: (context: SentenceContext) => Partial<Domain<string>>;
128
+ }
129
+ /**
130
+ * Create an expression-only domain (no keywords).
131
+ *
132
+ * Convenience alias for keywordOrExpressionDomain with empty keywords.
133
+ * Use this for free-text inputs: task names, descriptions, custom values.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const taskName = expressionDomain({
138
+ * color: 'rose',
139
+ * expression: textExpression({
140
+ * placeholder: 'task name',
141
+ * maxLength: 200,
142
+ * }),
143
+ * placeholder: 'a new task',
144
+ * });
145
+ * ```
146
+ */
147
+ export declare function expressionDomain(config: ExpressionDomainConfig): Domain<string>;
148
+ //# sourceMappingURL=keyword-or-expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyword-or-expression.d.ts","sourceRoot":"","sources":["../../../src/domains/keyword-or-expression.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Multi-select domain — toggle grid of options, group keyword shortcuts.
3
+ *
4
+ * The third archetype. Value is string[] — an ordered array of selected
5
+ * option values. Covers tags, day-sets, and any multi-choice value space.
6
+ *
7
+ * Display uses a "3 then count" rule: up to 3 labels comma-joined,
8
+ * then "{n} selected" at 4+.
9
+ */
10
+ import type { Domain, Keyword, SentenceContext } from '../core/types';
11
+ import { type KeywordConfig, type KeywordGroupItem } from './normalize-keywords';
12
+ /** Configuration for a multi-select domain. */
13
+ export interface MultiSelectDomainConfig {
14
+ /** Semantic color key */
15
+ color: string;
16
+ /** Available options (rendered as toggle pills in the popup). Accepts groups for visual grouping. */
17
+ options: KeywordGroupItem<string>[] | Keyword<string>[];
18
+ /**
19
+ * Group keywords — shortcuts that set multiple options at once.
20
+ * Selecting a keyword replaces the current selection entirely.
21
+ * E.g., { label: 'weekdays', value: ['mon', 'tue', 'wed', 'thu', 'fri'] }
22
+ */
23
+ keywords?: KeywordConfig<string[]>[] | Keyword<string[]>[];
24
+ /** Max selections (omit for unlimited) */
25
+ maxSelections?: number;
26
+ /**
27
+ * Label used when count display kicks in (4+ selections).
28
+ * E.g., "days" → "4 days", "instruments" → "5 instruments".
29
+ * Defaults to "selected".
30
+ */
31
+ countLabel?: string;
32
+ /** Default value — empty array if omitted (invalid → placeholder) */
33
+ default?: string[];
34
+ /** @deprecated Use `default` instead */
35
+ defaultValue?: string[];
36
+ /** Text shown in chip trigger when no options are selected */
37
+ placeholder?: string;
38
+ /** Context keys this domain reads from ancestor producers */
39
+ consumes?: string[];
40
+ /** Context keys this domain writes for descendant consumers */
41
+ produces?: string[];
42
+ /** Reconfigure domain when ancestor context changes */
43
+ onContextChange?: (context: SentenceContext) => Partial<Domain<string[]>>;
44
+ }
45
+ /** Check if a selection matches a group keyword's value set (order-independent). */
46
+ export declare function selectionMatchesKeyword(selection: ReadonlySet<string>, selectionLength: number, keywordValues: readonly string[]): boolean;
47
+ /**
48
+ * Create a multi-select domain.
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const daySet = multiSelectDomain({
53
+ * color: 'sage',
54
+ * options: [
55
+ * { label: 'Mon', value: 'mon' },
56
+ * { label: 'Tue', value: 'tue' },
57
+ * { label: 'Wed', value: 'wed' },
58
+ * // ...
59
+ * ],
60
+ * keywords: [
61
+ * { label: 'weekdays', value: ['mon', 'tue', 'wed', 'thu', 'fri'] },
62
+ * ],
63
+ * placeholder: 'which days',
64
+ * });
65
+ * ```
66
+ */
67
+ export declare function multiSelectDomain(config: MultiSelectDomainConfig): Domain<string[]>;
68
+ //# sourceMappingURL=multi-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-select.d.ts","sourceRoot":"","sources":["../../../src/domains/multi-select.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtE,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB;IACtC,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IAEd,qGAAqG;IACrG,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IAExD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IAE3D,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,uDAAuD;IACvD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CAC3E;AAKD,oFAAoF;AACpF,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,EAC9B,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,OAAO,CAKT;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CA0DnF"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Shared keyword normalization and domain utilities.
3
+ *
4
+ * Consumers can provide keyword shorthand:
5
+ * { value: 'daily' } → label='daily', display=undefined
6
+ * { value: 'daily', label: 'day' } → label='day', display=undefined
7
+ * { value: 'daily', label: 'day', display: 'day of the week' }
8
+ * → label='day', display='day of the week'
9
+ *
10
+ * Grouping (keyword-grouping.md):
11
+ * Keywords arrays accept KeywordGroup objects alongside plain configs.
12
+ * Groups carry label, layout, columns, prefix. Ungrouped keywords
13
+ * collect into one implicit group at the top.
14
+ *
15
+ * See builder-dx.md §4, keyword-grouping.md.
16
+ */
17
+ import type { Keyword } from '../core/types';
18
+ /** Shorthand keyword config accepted by domain factories. */
19
+ export interface KeywordConfig<T = string> {
20
+ value: T;
21
+ label?: string | ((context: Record<string, unknown>) => string);
22
+ display?: string;
23
+ partial?: boolean;
24
+ }
25
+ /** A named group of keywords rendered as a visual section in the popup. */
26
+ export interface KeywordGroup<T = string> {
27
+ /** Display label rendered above the keywords (omit for unlabeled group) */
28
+ label?: string;
29
+ /** Keywords in this group */
30
+ keywords: KeywordConfig<T>[];
31
+ /** Layout mode: 'flow' (default flex-wrap) or 'grid' (CSS grid) */
32
+ layout?: 'flow' | 'grid';
33
+ /** Grid column count (required when layout is 'grid') */
34
+ columns?: number;
35
+ /** Text rendered before the keyword pills (e.g., "the") */
36
+ prefix?: string;
37
+ }
38
+ /** A keyword config or a group of keyword configs. */
39
+ export type KeywordGroupItem<T = string> = KeywordConfig<T> | KeywordGroup<T>;
40
+ /** Normalized group ready for popup rendering. */
41
+ export interface NormalizedKeywordGroup<T = string> {
42
+ label?: string;
43
+ layout: 'flow' | 'grid';
44
+ columns?: number;
45
+ prefix?: string;
46
+ keywords: Keyword<T>[];
47
+ }
48
+ /** Type guard: is this item a KeywordGroup (has a `keywords` array, no `value`)? */
49
+ export declare function isKeywordGroup<T>(item: KeywordGroupItem<T>): item is KeywordGroup<T>;
50
+ /** Normalize shorthand keyword configs into full Keyword<T> objects. */
51
+ export declare function normalizeKeywords<T>(configs: KeywordConfig<T>[]): Keyword<T>[];
52
+ /**
53
+ * Normalize a mixed keywords array into grouped form.
54
+ *
55
+ * Returns both a flat keyword list (for validation, display, keyboard nav)
56
+ * and a grouped list (for popup rendering).
57
+ *
58
+ * Ungrouped KeywordConfig items are collected into a single implicit group
59
+ * placed before any explicit groups. If all items are ungrouped, the result
60
+ * is a single group with default config.
61
+ */
62
+ export declare function normalizeKeywordGroups<T>(items: KeywordGroupItem<T>[]): {
63
+ flat: Keyword<T>[];
64
+ groups: NormalizedKeywordGroup<T>[];
65
+ };
66
+ /**
67
+ * Build a value → display text map from normalized keywords.
68
+ * Uses display if present, falls back to label.
69
+ */
70
+ export declare function buildDisplayMap<T>(keywords: Keyword<T>[]): Map<T, string>;
71
+ /**
72
+ * Resolve the default value for a domain.
73
+ *
74
+ * Cascade: explicit default → deprecated defaultValue → placeholder-aware fallback.
75
+ * When placeholder is set, defaults to fallbackEmpty (user must choose).
76
+ * When no placeholder, defaults to first keyword if available.
77
+ */
78
+ export declare function resolveDefault<T>(config: {
79
+ default?: T;
80
+ defaultValue?: T;
81
+ placeholder?: string;
82
+ }, keywords: Keyword<unknown>[], firstKeywordValue: T | undefined, fallbackEmpty: T): T;
83
+ //# sourceMappingURL=normalize-keywords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-keywords.d.ts","sourceRoot":"","sources":["../../../src/domains/normalize-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,6DAA6D;AAC7D,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,MAAM;IACvC,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,MAAM;IACtC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,6BAA6B;IAC7B,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAE7B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAE9E,kDAAkD;AAClD,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,MAAM;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;CACxB;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,CAEpF;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAO9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,CAmC7D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAKzE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/D,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,EAC5B,iBAAiB,EAAE,CAAC,GAAG,SAAS,EAChC,aAAa,EAAE,CAAC,GACf,CAAC,CAKH"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Reference domain — external data with navigation/search popup.
3
+ *
4
+ * The fifth archetype. Value is an opaque reference ID (string).
5
+ * The consumer provides a ReferenceSource that fetches items on demand;
6
+ * Chipper provides tree navigation, search, and selection mechanics.
7
+ *
8
+ * Covers priority pickers (hierarchical tree), user pickers (flat search),
9
+ * and any domain where the value space lives outside the palette.
10
+ */
11
+ import type { Domain, Keyword, SentenceContext } from '../core/types';
12
+ /** A single item in the reference data set. */
13
+ export interface ReferenceItem {
14
+ /** Unique ID — becomes the chip value when selected */
15
+ id: string;
16
+ /** Display label */
17
+ label: string;
18
+ /** Whether this item has children (enables drill-in affordance) */
19
+ hasChildren?: boolean;
20
+ /**
21
+ * Whether this item can be selected. Default true.
22
+ * If false, the item is a navigation-only node (category, folder).
23
+ * Items with hasChildren can be both drillable and selectable.
24
+ */
25
+ selectable?: boolean;
26
+ }
27
+ /** Data source for a reference domain. */
28
+ export interface ReferenceSource {
29
+ /**
30
+ * Fetch items at a given path in the hierarchy.
31
+ * - Root level: path is []
32
+ * - One level deep: path is [rootItem]
33
+ * - Flat data: ignore path, return full list
34
+ *
35
+ * Called on popup open and on each drill-in navigation.
36
+ */
37
+ getItems: (path: ReferenceItem[]) => ReferenceItem[] | Promise<ReferenceItem[]>;
38
+ /**
39
+ * Search across the full data set.
40
+ * If omitted, the popup hides the search input.
41
+ */
42
+ search?: (query: string) => ReferenceItem[] | Promise<ReferenceItem[]>;
43
+ /**
44
+ * Resolve an ID to its display string.
45
+ * Called eagerly on chip mount to populate displayValue for saved references.
46
+ * If omitted, the raw ID is shown as the display value.
47
+ */
48
+ resolveDisplay?: (id: string) => string | Promise<string>;
49
+ }
50
+ /** Configuration for a reference domain. */
51
+ export interface ReferenceDomainConfig {
52
+ /** Semantic color key */
53
+ color: string;
54
+ /** Data source — provides items, search, display resolution */
55
+ source: ReferenceSource;
56
+ /**
57
+ * Shortcut keywords. Selected like enum keywords — bypass the popup.
58
+ * Useful for "none" or "any" sentinel values.
59
+ */
60
+ keywords?: Keyword<string>[];
61
+ /** Default value — empty string if omitted (invalid → placeholder) */
62
+ default?: string;
63
+ /** Text shown when value is invalid */
64
+ placeholder?: string;
65
+ /** Context keys this domain reads */
66
+ consumes?: string[];
67
+ /** Context keys this domain writes */
68
+ produces?: string[];
69
+ /** Reconfigure domain when ancestor context changes */
70
+ onContextChange?: (context: SentenceContext) => Partial<Domain<string>>;
71
+ }
72
+ /**
73
+ * Create a reference domain.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const priorityRef = referenceDomain({
78
+ * color: 'indigo',
79
+ * source: {
80
+ * getItems: (path) => fetchPrioritiesAt(path),
81
+ * search: (query) => searchPriorities(query),
82
+ * resolveDisplay: (id) => getPriorityPath(id),
83
+ * },
84
+ * placeholder: 'a priority',
85
+ * });
86
+ * ```
87
+ */
88
+ export declare function referenceDomain(config: ReferenceDomainConfig): Domain<string>;
89
+ //# sourceMappingURL=reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../../src/domains/reference.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGtE,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAC;IAEX,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IAEd,mEAAmE;IACnE,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAEhF;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAEvE;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3D;AAED,4CAA4C;AAC5C,MAAM,WAAW,qBAAqB;IACpC,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IAEd,+DAA+D;IAC/D,MAAM,EAAE,eAAe,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;IAE7B,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,uDAAuD;IACvD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;CACzE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC,CAkC7E"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SentenceProvider — wraps useReducer and popup state for a sentence instance.
3
+ *
4
+ * Components and hooks beneath this provider access sentence state via
5
+ * useSentence, useChip, and usePopup.
6
+ */
7
+ import type { SentenceDefinition } from '../core/types';
8
+ import type { SentenceState } from '../core/state';
9
+ export interface SentenceProviderProps {
10
+ definition: SentenceDefinition;
11
+ /** Saved values to restore on mount (from serialize()) */
12
+ initialValues?: Record<string, unknown>;
13
+ onChange?: (state: SentenceState) => void;
14
+ children: React.ReactNode;
15
+ }
16
+ export declare function SentenceProvider({ definition, initialValues, onChange, children }: SentenceProviderProps): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=SentenceProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SentenceProvider.d.ts","sourceRoot":"","sources":["../../../src/hooks/SentenceProvider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAKnD,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,qBAAqB,2CA2BxG"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * React context for a Chipper sentence instance.
3
+ *
4
+ * Carries the store, dispatch, definition, and popup state.
5
+ * One context per SentenceProvider — multiple Chipper instances
6
+ * on the same page get independent contexts.
7
+ */
8
+ import type { SentenceStore } from '../core/store';
9
+ import type { SentenceAction } from '../core/reducer';
10
+ import type { SentenceDefinition } from '../core/types';
11
+ /** Which chip popup is currently open, or null if none. */
12
+ export interface PopupState {
13
+ /** Currently open chip ID, or null */
14
+ chipId: string | null;
15
+ /** Clause containing the open chip, or null */
16
+ clauseId: string | null;
17
+ /** DOM element the popup positions relative to */
18
+ anchorElement: HTMLElement | null;
19
+ }
20
+ /** Value carried by SentenceContext. */
21
+ export interface SentenceContextValue {
22
+ store: SentenceStore;
23
+ dispatch: React.Dispatch<SentenceAction>;
24
+ definition: SentenceDefinition;
25
+ popupState: PopupState;
26
+ setPopupState: React.Dispatch<React.SetStateAction<PopupState>>;
27
+ }
28
+ /** Initial popup state — no popup open. */
29
+ export declare const closedPopup: PopupState;
30
+ export declare const SentenceContext: import("react").Context<SentenceContextValue | null>;
31
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/hooks/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,2DAA2D;AAC3D,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kDAAkD;IAClD,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;CACnC;AAED,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACzC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AAED,2CAA2C;AAC3C,eAAO,MAAM,WAAW,EAAE,UAIzB,CAAC;AAEF,eAAO,MAAM,eAAe,sDAAmD,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * React hooks — also the headless API.
3
+ *
4
+ * These hooks are the same ones used internally by the built-in components.
5
+ * Consumers import from 'chipper/headless' to use them without the default UI.
6
+ */
7
+ export { SentenceProvider, type SentenceProviderProps } from './SentenceProvider';
8
+ export { useSentence } from './useSentence';
9
+ export { useChip } from './useChip';
10
+ export { usePopup } from './usePopup';
11
+ export { useKeyboardNavigation, type KeyboardNavigationOptions, type KeyboardNavigationResult } from './useKeyboardNavigation';
12
+ export type { SentenceContextValue, PopupState } from './context';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,KAAK,yBAAyB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAC/H,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}