@sectile/terminal 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 (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/dist/accordion.d.ts +31 -0
  4. package/dist/accordion.d.ts.map +1 -0
  5. package/dist/accordion.js +76 -0
  6. package/dist/accordion.js.map +1 -0
  7. package/dist/alert-dialog.d.ts +18 -0
  8. package/dist/alert-dialog.d.ts.map +1 -0
  9. package/dist/alert-dialog.js +12 -0
  10. package/dist/alert-dialog.js.map +1 -0
  11. package/dist/calendar.d.ts +75 -0
  12. package/dist/calendar.d.ts.map +1 -0
  13. package/dist/calendar.js +217 -0
  14. package/dist/calendar.js.map +1 -0
  15. package/dist/carousel.d.ts +44 -0
  16. package/dist/carousel.d.ts.map +1 -0
  17. package/dist/carousel.js +129 -0
  18. package/dist/carousel.js.map +1 -0
  19. package/dist/checkbox-group.d.ts +19 -0
  20. package/dist/checkbox-group.d.ts.map +1 -0
  21. package/dist/checkbox-group.js +14 -0
  22. package/dist/checkbox-group.js.map +1 -0
  23. package/dist/checkbox.d.ts +17 -0
  24. package/dist/checkbox.d.ts.map +1 -0
  25. package/dist/checkbox.js +12 -0
  26. package/dist/checkbox.js.map +1 -0
  27. package/dist/combobox.d.ts +100 -0
  28. package/dist/combobox.d.ts.map +1 -0
  29. package/dist/combobox.js +286 -0
  30. package/dist/combobox.js.map +1 -0
  31. package/dist/date-field.d.ts +36 -0
  32. package/dist/date-field.d.ts.map +1 -0
  33. package/dist/date-field.js +46 -0
  34. package/dist/date-field.js.map +1 -0
  35. package/dist/date-picker.d.ts +38 -0
  36. package/dist/date-picker.d.ts.map +1 -0
  37. package/dist/date-picker.js +40 -0
  38. package/dist/date-picker.js.map +1 -0
  39. package/dist/date-range-picker.d.ts +38 -0
  40. package/dist/date-range-picker.d.ts.map +1 -0
  41. package/dist/date-range-picker.js +29 -0
  42. package/dist/date-range-picker.js.map +1 -0
  43. package/dist/date-time-field.d.ts +36 -0
  44. package/dist/date-time-field.d.ts.map +1 -0
  45. package/dist/date-time-field.js +133 -0
  46. package/dist/date-time-field.js.map +1 -0
  47. package/dist/date-time-picker.d.ts +38 -0
  48. package/dist/date-time-picker.d.ts.map +1 -0
  49. package/dist/date-time-picker.js +127 -0
  50. package/dist/date-time-picker.js.map +1 -0
  51. package/dist/date-time-range-picker.d.ts +38 -0
  52. package/dist/date-time-range-picker.d.ts.map +1 -0
  53. package/dist/date-time-range-picker.js +136 -0
  54. package/dist/date-time-range-picker.js.map +1 -0
  55. package/dist/dialog.d.ts +17 -0
  56. package/dist/dialog.d.ts.map +1 -0
  57. package/dist/dialog.js +12 -0
  58. package/dist/dialog.js.map +1 -0
  59. package/dist/disclosure.d.ts +22 -0
  60. package/dist/disclosure.d.ts.map +1 -0
  61. package/dist/disclosure.js +56 -0
  62. package/dist/disclosure.js.map +1 -0
  63. package/dist/feed.d.ts +28 -0
  64. package/dist/feed.d.ts.map +1 -0
  65. package/dist/feed.js +32 -0
  66. package/dist/feed.js.map +1 -0
  67. package/dist/grid.d.ts +40 -0
  68. package/dist/grid.d.ts.map +1 -0
  69. package/dist/grid.js +68 -0
  70. package/dist/grid.js.map +1 -0
  71. package/dist/index.d.ts +46 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +44 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/internal/checked-control.d.ts +23 -0
  76. package/dist/internal/checked-control.d.ts.map +1 -0
  77. package/dist/internal/checked-control.js +22 -0
  78. package/dist/internal/checked-control.js.map +1 -0
  79. package/dist/internal/controller.d.ts +6 -0
  80. package/dist/internal/controller.d.ts.map +1 -0
  81. package/dist/internal/controller.js +35 -0
  82. package/dist/internal/controller.js.map +1 -0
  83. package/dist/internal/disabled-items.d.ts +6 -0
  84. package/dist/internal/disabled-items.d.ts.map +1 -0
  85. package/dist/internal/disabled-items.js +15 -0
  86. package/dist/internal/disabled-items.js.map +1 -0
  87. package/dist/internal/facade.d.ts +44 -0
  88. package/dist/internal/facade.d.ts.map +1 -0
  89. package/dist/internal/facade.js +58 -0
  90. package/dist/internal/facade.js.map +1 -0
  91. package/dist/internal/menu-control.d.ts +34 -0
  92. package/dist/internal/menu-control.d.ts.map +1 -0
  93. package/dist/internal/menu-control.js +48 -0
  94. package/dist/internal/menu-control.js.map +1 -0
  95. package/dist/internal/popup-control.d.ts +24 -0
  96. package/dist/internal/popup-control.d.ts.map +1 -0
  97. package/dist/internal/popup-control.js +23 -0
  98. package/dist/internal/popup-control.js.map +1 -0
  99. package/dist/internal/semantic-controller.d.ts +20 -0
  100. package/dist/internal/semantic-controller.d.ts.map +1 -0
  101. package/dist/internal/semantic-controller.js +42 -0
  102. package/dist/internal/semantic-controller.js.map +1 -0
  103. package/dist/internal/text-input.d.ts +5 -0
  104. package/dist/internal/text-input.d.ts.map +1 -0
  105. package/dist/internal/text-input.js +53 -0
  106. package/dist/internal/text-input.js.map +1 -0
  107. package/dist/keyboard.d.ts +10 -0
  108. package/dist/keyboard.d.ts.map +1 -0
  109. package/dist/keyboard.js +16 -0
  110. package/dist/keyboard.js.map +1 -0
  111. package/dist/layout.d.ts +2 -0
  112. package/dist/layout.d.ts.map +1 -0
  113. package/dist/layout.js +24 -0
  114. package/dist/layout.js.map +1 -0
  115. package/dist/listbox.d.ts +87 -0
  116. package/dist/listbox.d.ts.map +1 -0
  117. package/dist/listbox.js +323 -0
  118. package/dist/listbox.js.map +1 -0
  119. package/dist/menu-button.d.ts +8 -0
  120. package/dist/menu-button.d.ts.map +1 -0
  121. package/dist/menu-button.js +11 -0
  122. package/dist/menu-button.js.map +1 -0
  123. package/dist/menu.d.ts +8 -0
  124. package/dist/menu.d.ts.map +1 -0
  125. package/dist/menu.js +11 -0
  126. package/dist/menu.js.map +1 -0
  127. package/dist/menubar.d.ts +8 -0
  128. package/dist/menubar.d.ts.map +1 -0
  129. package/dist/menubar.js +11 -0
  130. package/dist/menubar.js.map +1 -0
  131. package/dist/multi-thumb-slider.d.ts +32 -0
  132. package/dist/multi-thumb-slider.d.ts.map +1 -0
  133. package/dist/multi-thumb-slider.js +67 -0
  134. package/dist/multi-thumb-slider.js.map +1 -0
  135. package/dist/node.d.ts +15 -0
  136. package/dist/node.d.ts.map +1 -0
  137. package/dist/node.js +78 -0
  138. package/dist/node.js.map +1 -0
  139. package/dist/number-field.d.ts +44 -0
  140. package/dist/number-field.d.ts.map +1 -0
  141. package/dist/number-field.js +157 -0
  142. package/dist/number-field.js.map +1 -0
  143. package/dist/pagination.d.ts +35 -0
  144. package/dist/pagination.d.ts.map +1 -0
  145. package/dist/pagination.js +103 -0
  146. package/dist/pagination.js.map +1 -0
  147. package/dist/pin-input.d.ts +25 -0
  148. package/dist/pin-input.d.ts.map +1 -0
  149. package/dist/pin-input.js +30 -0
  150. package/dist/pin-input.js.map +1 -0
  151. package/dist/quantity-field.d.ts +45 -0
  152. package/dist/quantity-field.d.ts.map +1 -0
  153. package/dist/quantity-field.js +168 -0
  154. package/dist/quantity-field.js.map +1 -0
  155. package/dist/radio-group.d.ts +37 -0
  156. package/dist/radio-group.d.ts.map +1 -0
  157. package/dist/radio-group.js +126 -0
  158. package/dist/radio-group.js.map +1 -0
  159. package/dist/rating.d.ts +22 -0
  160. package/dist/rating.d.ts.map +1 -0
  161. package/dist/rating.js +38 -0
  162. package/dist/rating.js.map +1 -0
  163. package/dist/select.d.ts +41 -0
  164. package/dist/select.d.ts.map +1 -0
  165. package/dist/select.js +50 -0
  166. package/dist/select.js.map +1 -0
  167. package/dist/slider.d.ts +59 -0
  168. package/dist/slider.d.ts.map +1 -0
  169. package/dist/slider.js +156 -0
  170. package/dist/slider.js.map +1 -0
  171. package/dist/spin-button.d.ts +35 -0
  172. package/dist/spin-button.d.ts.map +1 -0
  173. package/dist/spin-button.js +78 -0
  174. package/dist/spin-button.js.map +1 -0
  175. package/dist/stepper.d.ts +19 -0
  176. package/dist/stepper.d.ts.map +1 -0
  177. package/dist/stepper.js +14 -0
  178. package/dist/stepper.js.map +1 -0
  179. package/dist/switch.d.ts +15 -0
  180. package/dist/switch.d.ts.map +1 -0
  181. package/dist/switch.js +12 -0
  182. package/dist/switch.js.map +1 -0
  183. package/dist/tabs.d.ts +42 -0
  184. package/dist/tabs.d.ts.map +1 -0
  185. package/dist/tabs.js +128 -0
  186. package/dist/tabs.js.map +1 -0
  187. package/dist/tags-input.d.ts +29 -0
  188. package/dist/tags-input.d.ts.map +1 -0
  189. package/dist/tags-input.js +27 -0
  190. package/dist/tags-input.js.map +1 -0
  191. package/dist/text.d.ts +60 -0
  192. package/dist/text.d.ts.map +1 -0
  193. package/dist/text.js +143 -0
  194. package/dist/text.js.map +1 -0
  195. package/dist/time-field.d.ts +36 -0
  196. package/dist/time-field.d.ts.map +1 -0
  197. package/dist/time-field.js +40 -0
  198. package/dist/time-field.js.map +1 -0
  199. package/dist/toggle-button.d.ts +15 -0
  200. package/dist/toggle-button.d.ts.map +1 -0
  201. package/dist/toggle-button.js +12 -0
  202. package/dist/toggle-button.js.map +1 -0
  203. package/dist/toolbar.d.ts +34 -0
  204. package/dist/toolbar.d.ts.map +1 -0
  205. package/dist/toolbar.js +108 -0
  206. package/dist/toolbar.js.map +1 -0
  207. package/dist/tooltip.d.ts +15 -0
  208. package/dist/tooltip.d.ts.map +1 -0
  209. package/dist/tooltip.js +12 -0
  210. package/dist/tooltip.js.map +1 -0
  211. package/dist/tree-grid.d.ts +94 -0
  212. package/dist/tree-grid.d.ts.map +1 -0
  213. package/dist/tree-grid.js +308 -0
  214. package/dist/tree-grid.js.map +1 -0
  215. package/dist/tree-view.d.ts +75 -0
  216. package/dist/tree-view.d.ts.map +1 -0
  217. package/dist/tree-view.js +213 -0
  218. package/dist/tree-view.js.map +1 -0
  219. package/dist/window-splitter.d.ts +19 -0
  220. package/dist/window-splitter.d.ts.map +1 -0
  221. package/dist/window-splitter.js +48 -0
  222. package/dist/window-splitter.js.map +1 -0
  223. package/package.json +273 -0
@@ -0,0 +1,129 @@
1
+ import { createFacadeConnection } from './internal/facade.js';
2
+ import { unwrap } from '@sectile/core/result';
3
+ import { createSequence } from '@sectile/core/sequence';
4
+ import { applyCarouselEvent, createCarouselState, getCarouselPosition, isCarouselRotationPaused, } from '@sectile/core/carousel';
5
+ import { createSemanticController } from './internal/semantic-controller.js';
6
+ export function createCarousel(options) {
7
+ return unwrap(tryCreateCarousel(options));
8
+ }
9
+ export function tryCreateCarousel(options) {
10
+ return createFacadeConnection(options, (options) => tryCreateCarouselConnection(options));
11
+ }
12
+ function tryCreateCarouselConnection(options) {
13
+ const slides = createSequence(options.slides);
14
+ if (!slides.ok)
15
+ return slides;
16
+ const autoplay = normalizeAutoplay(options.autoplay);
17
+ if (!autoplay.ok)
18
+ return autoplay;
19
+ const valueControlled = options.value !== undefined;
20
+ const pausedControlled = options.paused !== undefined;
21
+ const runtime = createSemanticController({
22
+ initial: createCarouselState(slides.value, options.value !== undefined ? options.value : options.defaultValue ?? options.slides[0] ?? null, options.paused ?? options.defaultPaused ?? false),
23
+ reducer: (state, event) => applyCarouselEvent(slides.value, state, event, options.policies),
24
+ reconcile: (previous, proposed) => createCarouselState(slides.value, valueControlled ? previous.cursor.current : proposed.cursor.current, pausedControlled ? previous.paused : proposed.paused, proposed.pauseReasons),
25
+ notify: (previous, proposed) => {
26
+ if (previous.cursor.current !== proposed.cursor.current)
27
+ options.onValueChange?.(proposed.cursor.current);
28
+ if (previous.paused !== proposed.paused)
29
+ options.onPausedChange?.(proposed.paused);
30
+ },
31
+ toEffect: (command) => command,
32
+ interaction: options,
33
+ });
34
+ return runtime.ok
35
+ ? { ok: true, value: new TerminalCarousel(options, slides.value, runtime.value, autoplay.value, valueControlled, pausedControlled) }
36
+ : runtime;
37
+ }
38
+ class TerminalCarousel {
39
+ #options;
40
+ #slides;
41
+ #runtime;
42
+ #autoplay;
43
+ #valueControlled;
44
+ #pausedControlled;
45
+ #timer = noCarouselTimer;
46
+ constructor(options, slides, runtime, autoplay, valueControlled, pausedControlled) {
47
+ this.#options = options;
48
+ this.#slides = slides;
49
+ this.#runtime = runtime;
50
+ this.#autoplay = autoplay;
51
+ this.#valueControlled = valueControlled;
52
+ this.#pausedControlled = pausedControlled;
53
+ this.#resetTimer();
54
+ }
55
+ getSnapshot() { return this.#runtime.getSnapshot(); }
56
+ getPosition() { return getCarouselPosition(this.#slides, this.getSnapshot().state); }
57
+ syncControlledValues(values) {
58
+ if (this.#valueControlled !== (values.value !== undefined) || this.#pausedControlled !== (values.paused !== undefined)) {
59
+ return { ok: false, error: { class: 'construction', code: 'controlled-shape-mismatch', message: 'Controlled carousel values must preserve their construction-time shape.' } };
60
+ }
61
+ const state = this.getSnapshot().state;
62
+ const result = this.#runtime.replace(createCarouselState(this.#slides, this.#valueControlled ? values.value : state.cursor.current, this.#pausedControlled ? values.paused : state.paused, state.pauseReasons));
63
+ if (result.ok) {
64
+ this.#resetTimer();
65
+ this.#options.onUpdate?.();
66
+ }
67
+ return result;
68
+ }
69
+ handleEvent(event) {
70
+ const before = this.getSnapshot().state.cursor.current;
71
+ const result = this.#runtime.handle(event);
72
+ if (result.ok) {
73
+ for (const command of result.commands)
74
+ this.#options.onAnnounce?.(command.id);
75
+ this.#resetTimer();
76
+ if (this.#autoplay !== null && this.#options.policies?.wrap === false && event === 'next' && before === this.getSnapshot().state.cursor.current)
77
+ this.#clearTimer();
78
+ }
79
+ this.#options.onUpdate?.();
80
+ return result.ok;
81
+ }
82
+ handleKeyboardInput(input) {
83
+ const vertical = this.#options.orientation === 'vertical';
84
+ const event = input.key === (vertical ? 'down' : 'right') ? 'next'
85
+ : input.key === (vertical ? 'up' : 'left') ? 'previous'
86
+ : input.key === 'home' ? 'first'
87
+ : input.key === 'end' ? 'last'
88
+ : input.key === 'space' ? 'toggle-pause'
89
+ : null;
90
+ if (event === null)
91
+ return false;
92
+ this.handleEvent(event);
93
+ if (this.#autoplay?.stopOnInteraction && event !== 'toggle-pause')
94
+ this.handleEvent('pause');
95
+ return true;
96
+ }
97
+ disconnect() { this.#clearTimer(); }
98
+ #resetTimer() {
99
+ this.#clearTimer();
100
+ if (this.#autoplay === null || this.#slides.size < 2 || isCarouselRotationPaused(this.getSnapshot().state))
101
+ return;
102
+ this.#timer = this.#autoplay.scheduler.schedule(() => {
103
+ this.#timer = noCarouselTimer;
104
+ this.handleEvent('next');
105
+ }, this.#autoplay.delayMs);
106
+ }
107
+ #clearTimer() {
108
+ if (this.#timer === noCarouselTimer || this.#autoplay === null)
109
+ return;
110
+ this.#autoplay.scheduler.cancel(this.#timer);
111
+ this.#timer = noCarouselTimer;
112
+ }
113
+ }
114
+ const noCarouselTimer = Symbol('no-carousel-timer');
115
+ function normalizeAutoplay(autoplay) {
116
+ if (autoplay === undefined || autoplay === false)
117
+ return { ok: true, value: null };
118
+ const config = autoplay === true ? {} : autoplay;
119
+ const delayMs = config.delayMs ?? 5000;
120
+ if (!Number.isFinite(delayMs) || delayMs <= 0) {
121
+ return { ok: false, error: { class: 'construction', code: 'carousel-autoplay-delay-invalid', message: 'Carousel autoplay delay must be a positive finite number.' } };
122
+ }
123
+ const scheduler = config.scheduler ?? {
124
+ schedule: (callback, delay) => globalThis.setTimeout(callback, delay),
125
+ cancel: (token) => { globalThis.clearTimeout(token); },
126
+ };
127
+ return { ok: true, value: { delayMs, stopOnInteraction: config.stopOnInteraction ?? true, scheduler } };
128
+ }
129
+ //# sourceMappingURL=carousel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carousel.js","sourceRoot":"","sources":["../src/carousel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type FacadeConnection } from './internal/facade.js';
2
+ import type { Result, StableID } from '@sectile/core';
3
+ import type { CheckboxGroupEvent, CheckboxGroupState } from '@sectile/core/checkbox-group';
4
+ import type { RevisionSnapshot } from '@sectile/core/revision';
5
+ import { type ListboxOptions } from './listbox.js';
6
+ import type { TerminalKeyboardInput } from './keyboard.js';
7
+ export type CheckboxGroupOptions<ID extends StableID = StableID> = Omit<ListboxOptions<ID>, 'selectionMode'>;
8
+ export interface CheckboxGroupConnection<ID extends StableID = StableID> {
9
+ getSnapshot(): RevisionSnapshot<CheckboxGroupState<ID>>;
10
+ syncControlledValues(values: {
11
+ readonly value?: readonly ID[];
12
+ readonly highlightedValue?: ID | null;
13
+ }): Result<RevisionSnapshot<CheckboxGroupState<ID>>>;
14
+ handleEvent(event: CheckboxGroupEvent<ID>): boolean;
15
+ handleKeyboardInput(input: TerminalKeyboardInput): boolean;
16
+ }
17
+ export declare function createCheckboxGroup<ID extends StableID>(options: CheckboxGroupOptions<ID>): FacadeConnection<CheckboxGroupConnection<ID>>;
18
+ export declare function tryCreateCheckboxGroup<ID extends StableID>(options: CheckboxGroupOptions<ID>): Result<FacadeConnection<CheckboxGroupConnection<ID>>>;
19
+ //# sourceMappingURL=checkbox-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox-group.d.ts","sourceRoot":"","sources":["../src/checkbox-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAErF,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAA4C,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,MAAM,oBAAoB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;AAC7G,MAAM,WAAW,uBAAuB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IACrE,WAAW,IAAI,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,oBAAoB,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,GAAG,IAAI,CAAA;KAAE,GAAG,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1J,WAAW,CAAC,KAAK,EAAE,kBAAkB,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC;IACpD,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC;CAC5D;AACD,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,QAAQ,EAAE,OAAO,EAAE,oBAAoB,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAEzI;AAED,wBAAgB,sBAAsB,CAAC,EAAE,SAAS,QAAQ,EAAE,OAAO,EAAE,oBAAoB,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC,CAAC,CAEpJ"}
@@ -0,0 +1,14 @@
1
+ import { createFacadeConnection } from './internal/facade.js';
2
+ import { unwrap } from '@sectile/core/result';
3
+ import { tryCreateListbox } from './listbox.js';
4
+ export function createCheckboxGroup(options) {
5
+ return unwrap(tryCreateCheckboxGroup(options));
6
+ }
7
+ export function tryCreateCheckboxGroup(options) {
8
+ return createFacadeConnection(options, (options) => tryCreateCheckboxGroupConnection(options));
9
+ }
10
+ function tryCreateCheckboxGroupConnection(options) {
11
+ const result = tryCreateListbox({ ...options, selectionMode: 'multiple' });
12
+ return result.ok ? { ok: true, value: result.value } : result;
13
+ }
14
+ //# sourceMappingURL=checkbox-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox-group.js","sourceRoot":"","sources":["../src/checkbox-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAyB,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAI9C,OAAO,EAAE,gBAAgB,EAA+C,MAAM,cAAc,CAAC;AAU7F,MAAM,UAAU,mBAAmB,CAAsB,OAAiC;IACxF,OAAO,MAAM,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAsB,OAAiC;IAC3F,OAAO,sBAAsB,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,gCAAgC,CAAC,OAAO,CAAC,CAAC,CAAC;AACjG,CAAC;AAED,SAAS,gCAAgC,CAAsB,OAAiC;IAC9F,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAA6D,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACxH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type FacadeConnection } from './internal/facade.js';
2
+ import type { Result } from '@sectile/core';
3
+ import { type CheckboxEvent, type CheckboxPolicies, type CheckboxState, type CheckboxValue } from '@sectile/core/checkbox';
4
+ import { type TerminalCheckedControl } from './internal/checked-control.js';
5
+ export interface CheckboxOptions {
6
+ readonly value?: CheckboxValue;
7
+ readonly defaultValue?: CheckboxValue;
8
+ readonly policies?: CheckboxPolicies;
9
+ readonly disabled?: boolean;
10
+ readonly readOnly?: boolean;
11
+ readonly onValueChange?: (value: CheckboxValue) => void;
12
+ readonly onUpdate?: () => void;
13
+ }
14
+ export type CheckboxConnection = TerminalCheckedControl<CheckboxState, CheckboxEvent, CheckboxValue>;
15
+ export declare function createCheckbox(options?: CheckboxOptions): FacadeConnection<CheckboxConnection>;
16
+ export declare function tryCreateCheckbox(options?: CheckboxOptions): Result<FacadeConnection<CheckboxConnection>>;
17
+ //# sourceMappingURL=checkbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../src/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAErF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAAC,OAAO,EAAiE,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAAC,OAAO,EAAgC,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAClV,MAAM,WAAW,eAAe;IAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE;AACnS,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AACrG,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAoB,GAAG,gBAAgB,CAAC,kBAAkB,CAAC,CAElG;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,eAAoB,GAAG,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAE7G"}
@@ -0,0 +1,12 @@
1
+ import { createFacadeConnection } from './internal/facade.js';
2
+ import { unwrap } from '@sectile/core/result';
3
+ import { applyCheckboxEvent, createCheckboxState } from '@sectile/core/checkbox';
4
+ import { createTerminalCheckedControl } from './internal/checked-control.js';
5
+ export function createCheckbox(options = {}) {
6
+ return unwrap(tryCreateCheckbox(options));
7
+ }
8
+ export function tryCreateCheckbox(options = {}) {
9
+ return createFacadeConnection(options, (options) => tryCreateCheckboxConnection(options));
10
+ }
11
+ function tryCreateCheckboxConnection(options = {}) { return createTerminalCheckedControl({ controlled: options.value !== undefined, initial: createCheckboxState(options.value ?? options.defaultValue ?? false, options.policies), toggleEvent: 'toggle', reducer: (state, event) => applyCheckboxEvent(state, event, options.policies), create: (value) => createCheckboxState(value, options.policies), read: (state) => state.checked, interaction: options, onChange: options.onValueChange, onUpdate: options.onUpdate }); }
12
+ //# sourceMappingURL=checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../src/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAyB,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAA2G,MAAM,wBAAwB,CAAC;AAAC,OAAO,EAAE,4BAA4B,EAA+B,MAAM,+BAA+B,CAAC;AAGlV,MAAM,UAAU,cAAc,CAAC,OAAO,GAAoB,EAAE;IAC1D,OAAO,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAO,GAAoB,EAAE;IAC7D,OAAO,sBAAsB,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,2BAA2B,CAAC,OAAO,GAAoB,EAAE,IAAgC,OAAO,4BAA4B,CAA+D,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,YAAY,IAAI,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,100 @@
1
+ import { type FacadeConnection } from './internal/facade.js';
2
+ import type { Result, StableID } from '@sectile/core';
3
+ import { type ComboboxCommand, type ComboboxEvent, type ComboboxPolicies, type ComboboxState } from '@sectile/core/combobox';
4
+ import { type RevisionResult, type RevisionSnapshot } from '@sectile/core/revision';
5
+ import { type Sequence } from '@sectile/core/sequence';
6
+ import { type TextEditingState } from '@sectile/core/text';
7
+ import { type TextInput } from './text.js';
8
+ import type { TerminalKeyboardInput } from './keyboard.js';
9
+ export type KeyboardInput = TerminalKeyboardInput;
10
+ export type ComboboxEffect<ID extends StableID = StableID> = {
11
+ readonly type: 'highlight-candidate';
12
+ readonly id: ID;
13
+ } | {
14
+ readonly type: 'submit-candidate';
15
+ readonly id: ID;
16
+ };
17
+ export interface ComboboxValueChangeDetails<ID extends StableID = StableID> {
18
+ readonly value: ID | null;
19
+ readonly previousValue: ID | null;
20
+ }
21
+ export interface ComboboxInputStateChangeDetails {
22
+ readonly value: TextEditingState;
23
+ readonly previousValue: TextEditingState;
24
+ }
25
+ export interface ComboboxOpenChangeDetails {
26
+ readonly value: boolean;
27
+ readonly previousValue: boolean;
28
+ }
29
+ export interface ComboboxHighlightChangeDetails<ID extends StableID = StableID> {
30
+ readonly value: ID | null;
31
+ readonly previousValue: ID | null;
32
+ }
33
+ export interface ComboboxControllerOptions<ID extends StableID = StableID> {
34
+ readonly domain: Sequence<ID>;
35
+ readonly labels: ReadonlyMap<ID, string>;
36
+ readonly policies?: ComboboxPolicies<ID>;
37
+ readonly value?: ID | null;
38
+ readonly defaultValue?: ID | null;
39
+ readonly inputState?: TextEditingState;
40
+ readonly defaultInputState?: TextEditingState;
41
+ readonly open?: boolean;
42
+ readonly defaultOpen?: boolean;
43
+ readonly highlightedValue?: ID | null;
44
+ readonly defaultHighlightedValue?: ID | null;
45
+ readonly disabled?: boolean;
46
+ readonly readOnly?: boolean;
47
+ readonly onValueChange?: (change: ComboboxValueChangeDetails<ID>) => void;
48
+ readonly onInputStateChange?: (change: ComboboxInputStateChangeDetails) => void;
49
+ readonly onOpenChange?: (change: ComboboxOpenChangeDetails) => void;
50
+ readonly onHighlightedValueChange?: (change: ComboboxHighlightChangeDetails<ID>) => void;
51
+ }
52
+ export interface ComboboxControlledValues<ID extends StableID = StableID> {
53
+ readonly value?: ID | null;
54
+ readonly inputState?: TextEditingState;
55
+ readonly open?: boolean;
56
+ readonly highlightedValue?: ID | null;
57
+ }
58
+ export interface ComboboxController<ID extends StableID = StableID> {
59
+ readonly domain: Sequence<ID>;
60
+ readonly labels: ReadonlyMap<ID, string>;
61
+ getSnapshot(): RevisionSnapshot<ComboboxState<ID>>;
62
+ syncControlledValues(values: ComboboxControlledValues<ID>): Result<RevisionSnapshot<ComboboxState<ID>>>;
63
+ handleKeyboardInput(input: KeyboardInput, expectedRevision?: number): RevisionResult<ComboboxState<ID>, ComboboxEffect<ID>>;
64
+ handleTextInput(input: TextInput, expectedRevision?: number): RevisionResult<ComboboxState<ID>, ComboboxEffect<ID>>;
65
+ }
66
+ export interface ComboboxItem<ID extends StableID = StableID> {
67
+ readonly id: ID;
68
+ readonly label: string;
69
+ }
70
+ export interface ComboboxTransitionDetails<ID extends StableID = StableID> {
71
+ readonly event: ComboboxEvent<ID>;
72
+ readonly result: RevisionResult<ComboboxState<ID>, ComboboxEffect<ID>>;
73
+ }
74
+ export interface ComboboxConnectionOptions<ID extends StableID = StableID> {
75
+ readonly controller: ComboboxController<ID>;
76
+ readonly disabled?: boolean;
77
+ readonly readOnly?: boolean;
78
+ readonly onAccept?: (id: ID) => void;
79
+ readonly onTransition?: (details: ComboboxTransitionDetails<ID>) => void;
80
+ readonly onUpdate?: () => void;
81
+ }
82
+ export interface ComboboxConnection<ID extends StableID = StableID> {
83
+ readonly domain: Sequence<ID>;
84
+ readonly labels: ReadonlyMap<ID, string>;
85
+ getSnapshot(): RevisionSnapshot<ComboboxState<ID>>;
86
+ getInputValue(): string;
87
+ syncControlledValues(values: ComboboxControlledValues<ID>): Result<RevisionSnapshot<ComboboxState<ID>>>;
88
+ handleKeyboardInput(input: KeyboardInput): boolean;
89
+ }
90
+ export type ComboboxOptions<ID extends StableID = StableID> = Omit<ComboboxControllerOptions<ID>, 'domain' | 'labels'> & Omit<ComboboxConnectionOptions<ID>, 'controller'> & {
91
+ readonly items: readonly ComboboxItem<ID>[];
92
+ };
93
+ export declare function createComboboxController<ID extends StableID>(options: ComboboxControllerOptions<ID>): Result<ComboboxController<ID>>;
94
+ export declare function createCombobox<ID extends StableID>(options: ComboboxOptions<ID>): FacadeConnection<ComboboxConnection<ID>>;
95
+ export declare function tryCreateCombobox<ID extends StableID>(options: ComboboxOptions<ID>): Result<FacadeConnection<ComboboxConnection<ID>>>;
96
+ export declare function connectCombobox<ID extends StableID>(options: ComboboxConnectionOptions<ID>): ComboboxConnection<ID>;
97
+ export declare function toComboboxEvent<ID extends StableID = StableID>(input: KeyboardInput): ComboboxEvent<ID> | null;
98
+ export declare function toComboboxTextEvent<ID extends StableID = StableID>(input: TextInput): ComboboxEvent<ID> | null;
99
+ export declare function toComboboxEffect<ID extends StableID>(command: ComboboxCommand<ID>): ComboboxEffect<ID>;
100
+ //# sourceMappingURL=combobox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../src/combobox.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAErF,OAAO,KAAK,EAAE,MAAM,EAAgB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAM5B,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAG3D,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAElD,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,IACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,0BAA0B,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IACxE,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,EAAE,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;CAC1C;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,8BAA8B,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAC5E,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,EAAE,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,yBAAyB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IACvE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gBAAgB,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,0BAA0B,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,+BAA+B,KAAK,IAAI,CAAC;IAChF,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAC;IACpE,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC,MAAM,EAAE,8BAA8B,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;CAC1F;AAED,MAAM,WAAW,wBAAwB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAChE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,IAAI,gBAAgB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,oBAAoB,CAClB,MAAM,EAAE,wBAAwB,CAAC,EAAE,CAAC,GACnC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,mBAAmB,CACjB,KAAK,EAAE,aAAa,EACpB,gBAAgB,CAAC,EAAE,MAAM,GACxB,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,eAAe,CACb,KAAK,EAAE,SAAS,EAChB,gBAAgB,CAAC,EAAE,MAAM,GACxB,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAC1D,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,yBAAyB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IACvE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,yBAAyB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IACvE,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAChE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,IAAI,gBAAgB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,aAAa,IAAI,MAAM,CAAC;IACxB,oBAAoB,CAClB,MAAM,EAAE,wBAAwB,CAAC,EAAE,CAAC,GACnC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;CACpD;AAED,MAAM,MAAM,eAAe,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,IACxD,IAAI,CAAC,yBAAyB,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC,GACtD,IAAI,CAAC,yBAAyB,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,GACjD;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,CAAC,EAAE,CAAC,EAAE,CAAA;CAAE,CAAC;AAEpD,wBAAgB,wBAAwB,CAAC,EAAE,SAAS,QAAQ,EAC1D,OAAO,EAAE,yBAAyB,CAAC,EAAE,CAAC,GACrC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAwBhC;AAED,wBAAgB,cAAc,CAAC,EAAE,SAAS,QAAQ,EAChD,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC,GAC3B,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAE1C;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,QAAQ,EACnD,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC,GAC3B,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAElD;AAaD,wBAAgB,eAAe,CAAC,EAAE,SAAS,QAAQ,EACjD,OAAO,EAAE,yBAAyB,CAAC,EAAE,CAAC,GACrC,kBAAkB,CAAC,EAAE,CAAC,CAExB;AAED,wBAAgB,eAAe,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,EAC5D,KAAK,EAAE,aAAa,GACnB,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,CAM1B;AAED,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,EAChE,KAAK,EAAE,SAAS,GACf,aAAa,CAAC,EAAE,CAAC,GAAG,IAAI,CAG1B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,QAAQ,EAClD,OAAO,EAAE,eAAe,CAAC,EAAE,CAAC,GAC3B,cAAc,CAAC,EAAE,CAAC,CAIpB"}
@@ -0,0 +1,286 @@
1
+ import { createFacadeConnection } from './internal/facade.js';
2
+ import { unwrap } from '@sectile/core/result';
3
+ import { createInteractionState, requireInteraction } from '@sectile/core/interaction';
4
+ import { applyComboboxEvent, createComboboxState, } from '@sectile/core/combobox';
5
+ import { createRevisionSnapshot, rejectRevisionInput, } from '@sectile/core/revision';
6
+ import { createSequence } from '@sectile/core/sequence';
7
+ import { createTextEditingState, } from '@sectile/core/text';
8
+ import { applyControllerEvent, sameControllerState, synchronizeControllerState, } from './internal/controller.js';
9
+ import { toTextEvent } from './text.js';
10
+ import { toTerminalTextInput } from './internal/text-input.js';
11
+ export function createComboboxController(options) {
12
+ const value = options.value !== undefined ? options.value : options.defaultValue ?? null;
13
+ const requestedInput = options.inputState !== undefined
14
+ ? options.inputState
15
+ : options.defaultInputState;
16
+ const inputState = requestedInput === undefined
17
+ ? createTextEditingState()
18
+ : { ok: true, value: requestedInput };
19
+ if (!inputState.ok)
20
+ return inputState;
21
+ const initial = createComboboxState(options.domain, {
22
+ text: inputState.value,
23
+ popupOpen: options.open !== undefined ? options.open : options.defaultOpen ?? false,
24
+ current: options.highlightedValue !== undefined
25
+ ? options.highlightedValue
26
+ : options.defaultHighlightedValue ?? null,
27
+ selected: value === null ? [] : [value],
28
+ anchor: value,
29
+ });
30
+ if (!initial.ok)
31
+ return initial;
32
+ const snapshot = createRevisionSnapshot(initial.value);
33
+ if (!snapshot.ok)
34
+ return snapshot;
35
+ const interaction = createInteractionState(options);
36
+ if (!interaction.ok)
37
+ return interaction;
38
+ return { ok: true, value: new TerminalComboboxController(options, interaction.value, snapshot.value) };
39
+ }
40
+ export function createCombobox(options) {
41
+ return unwrap(tryCreateCombobox(options));
42
+ }
43
+ export function tryCreateCombobox(options) {
44
+ return createFacadeConnection(options, (options) => tryCreateComboboxConnection(options));
45
+ }
46
+ function tryCreateComboboxConnection(options) {
47
+ const domain = createSequence(options.items.map((item) => item.id));
48
+ if (!domain.ok)
49
+ return domain;
50
+ const labels = new Map(options.items.map((item) => [item.id, item.label]));
51
+ const controller = createComboboxController({ ...options, domain: domain.value, labels });
52
+ if (!controller.ok)
53
+ return controller;
54
+ return { ok: true, value: connectCombobox({ ...options, controller: controller.value }) };
55
+ }
56
+ export function connectCombobox(options) {
57
+ return new TerminalComboboxConnection(options);
58
+ }
59
+ export function toComboboxEvent(input) {
60
+ if (input.key === 'down')
61
+ return 'next';
62
+ if (input.key === 'up')
63
+ return 'previous';
64
+ if (input.key === 'escape')
65
+ return 'close';
66
+ if (input.key === 'enter')
67
+ return 'accept';
68
+ return null;
69
+ }
70
+ export function toComboboxTextEvent(input) {
71
+ const event = toTextEvent(input);
72
+ return event === null ? null : Object.freeze({ type: 'text', event });
73
+ }
74
+ export function toComboboxEffect(command) {
75
+ return Object.freeze(command.type === 'focus'
76
+ ? { type: 'highlight-candidate', id: command.id }
77
+ : { type: 'submit-candidate', id: command.id });
78
+ }
79
+ class TerminalComboboxConnection {
80
+ domain;
81
+ labels;
82
+ #controller;
83
+ #onAccept;
84
+ #onTransition;
85
+ #onUpdate;
86
+ constructor(options) {
87
+ this.#controller = options.controller;
88
+ this.domain = options.controller.domain;
89
+ this.labels = options.controller.labels;
90
+ this.#onAccept = options.onAccept;
91
+ this.#onTransition = options.onTransition;
92
+ this.#onUpdate = options.onUpdate;
93
+ }
94
+ getSnapshot() {
95
+ return this.#controller.getSnapshot();
96
+ }
97
+ getInputValue() {
98
+ return this.#controller.getSnapshot().state.text.snapshot.text;
99
+ }
100
+ syncControlledValues(values) {
101
+ const result = this.#controller.syncControlledValues(values);
102
+ if (result.ok)
103
+ this.#onUpdate?.();
104
+ return result;
105
+ }
106
+ handleKeyboardInput(input) {
107
+ const keyboardEvent = toComboboxEvent(input);
108
+ if (keyboardEvent !== null) {
109
+ const result = this.#controller.handleKeyboardInput(input);
110
+ if (result.ok)
111
+ this.#applyEffects(result.commands);
112
+ this.#onTransition?.(Object.freeze({ event: keyboardEvent, result }));
113
+ if (result.ok)
114
+ this.#onUpdate?.();
115
+ return result.ok;
116
+ }
117
+ const textInput = toTerminalTextInput(this.#controller.getSnapshot().state.text, input);
118
+ if (textInput === null)
119
+ return false;
120
+ const event = toComboboxTextEvent(textInput);
121
+ const result = this.#controller.handleTextInput(textInput);
122
+ if (result.ok)
123
+ this.#applyEffects(result.commands);
124
+ if (event !== null)
125
+ this.#onTransition?.(Object.freeze({ event, result }));
126
+ if (result.ok)
127
+ this.#onUpdate?.();
128
+ return result.ok;
129
+ }
130
+ #applyEffects(effects) {
131
+ for (const effect of effects) {
132
+ if (effect.type === 'submit-candidate')
133
+ this.#onAccept?.(effect.id);
134
+ }
135
+ }
136
+ }
137
+ class TerminalComboboxController {
138
+ domain;
139
+ labels;
140
+ #domain;
141
+ #labels;
142
+ #policies;
143
+ #interaction;
144
+ #valueControlled;
145
+ #inputStateControlled;
146
+ #openControlled;
147
+ #highlightControlled;
148
+ #onValueChange;
149
+ #onInputStateChange;
150
+ #onOpenChange;
151
+ #onHighlightedValueChange;
152
+ #snapshot;
153
+ constructor(options, interaction, snapshot) {
154
+ this.domain = options.domain;
155
+ this.labels = options.labels;
156
+ this.#domain = options.domain;
157
+ this.#labels = options.labels;
158
+ this.#policies = options.policies ?? {};
159
+ this.#interaction = interaction;
160
+ this.#valueControlled = options.value !== undefined;
161
+ this.#inputStateControlled = options.inputState !== undefined;
162
+ this.#openControlled = options.open !== undefined;
163
+ this.#highlightControlled = options.highlightedValue !== undefined;
164
+ this.#onValueChange = options.onValueChange;
165
+ this.#onInputStateChange = options.onInputStateChange;
166
+ this.#onOpenChange = options.onOpenChange;
167
+ this.#onHighlightedValueChange = options.onHighlightedValueChange;
168
+ this.#snapshot = snapshot;
169
+ }
170
+ getSnapshot() {
171
+ return this.#snapshot;
172
+ }
173
+ syncControlledValues(values) {
174
+ const error = controlledInputError(this.#valueControlled, this.#inputStateControlled, this.#openControlled, this.#highlightControlled, values);
175
+ if (error !== null)
176
+ return { ok: false, error };
177
+ const selected = this.#valueControlled
178
+ ? values.value
179
+ : selectedValue(this.#snapshot.state);
180
+ const state = createComboboxState(this.#domain, {
181
+ text: this.#inputStateControlled
182
+ ? values.inputState
183
+ : this.#snapshot.state.text,
184
+ popupOpen: this.#openControlled
185
+ ? values.open
186
+ : this.#snapshot.state.popupOpen,
187
+ current: this.#highlightControlled
188
+ ? values.highlightedValue
189
+ : this.#snapshot.state.cursor.current,
190
+ selected: selected === null ? [] : [selected],
191
+ anchor: this.#valueControlled ? selected : this.#snapshot.state.selection.anchor,
192
+ });
193
+ const snapshot = synchronizeControllerState(this.#snapshot, state);
194
+ if (!snapshot.ok)
195
+ return snapshot;
196
+ this.#snapshot = snapshot.value;
197
+ return snapshot;
198
+ }
199
+ handleKeyboardInput(input, expectedRevision = this.#snapshot.revision) {
200
+ const event = toComboboxEvent(input);
201
+ return event === null
202
+ ? rejectRevisionInput(this.#snapshot, {
203
+ class: 'transition-rejection',
204
+ code: 'unsupported-terminal-key',
205
+ message: 'Terminal keyboard input does not map to a combobox semantic event.',
206
+ details: { key: input.key },
207
+ })
208
+ : this.#applyEvent(event, expectedRevision);
209
+ }
210
+ handleTextInput(input, expectedRevision = this.#snapshot.revision) {
211
+ const event = toComboboxTextEvent(input);
212
+ return event === null
213
+ ? rejectRevisionInput(this.#snapshot, {
214
+ class: 'transition-rejection',
215
+ code: 'unsupported-terminal-text-input',
216
+ message: 'Terminal text input does not map to a combobox semantic event.',
217
+ })
218
+ : this.#applyEvent(event, expectedRevision);
219
+ }
220
+ #applyEvent(event, expectedRevision) {
221
+ const permitted = requireInteraction(this.#interaction, comboboxIntent(event));
222
+ if (!permitted.ok)
223
+ return rejectRevisionInput(this.#snapshot, permitted.error);
224
+ const result = applyControllerEvent(this.#snapshot, expectedRevision, event, (state, semanticEvent) => applyComboboxEvent(this.#domain, this.#labels, state, semanticEvent, this.#policies), (previous, proposed) => controlledState(this.#domain, previous, proposed, this.#valueControlled, this.#inputStateControlled, this.#openControlled, this.#highlightControlled), (previous, proposed) => this.#notify(previous, proposed), toComboboxEffect);
225
+ if (result.ok)
226
+ this.#snapshot = result.snapshot;
227
+ return result;
228
+ }
229
+ #notify(previous, proposed) {
230
+ const previousValue = selectedValue(previous);
231
+ const value = selectedValue(proposed);
232
+ if (previousValue !== value)
233
+ this.#onValueChange?.(Object.freeze({ value, previousValue }));
234
+ if (!sameControllerState(previous.text, proposed.text)) {
235
+ this.#onInputStateChange?.(Object.freeze({
236
+ value: proposed.text,
237
+ previousValue: previous.text,
238
+ }));
239
+ }
240
+ if (previous.popupOpen !== proposed.popupOpen) {
241
+ this.#onOpenChange?.(Object.freeze({
242
+ value: proposed.popupOpen,
243
+ previousValue: previous.popupOpen,
244
+ }));
245
+ }
246
+ if (previous.cursor.current !== proposed.cursor.current) {
247
+ this.#onHighlightedValueChange?.(Object.freeze({
248
+ value: proposed.cursor.current,
249
+ previousValue: previous.cursor.current,
250
+ }));
251
+ }
252
+ }
253
+ }
254
+ function comboboxIntent(event) {
255
+ return event === 'next' || event === 'previous' || event === 'close' ? 'navigate' : 'mutate';
256
+ }
257
+ function controlledState(domain, previous, proposed, valueControlled, inputStateControlled, openControlled, highlightControlled) {
258
+ return createComboboxState(domain, {
259
+ text: inputStateControlled ? previous.text : proposed.text,
260
+ popupOpen: openControlled ? previous.popupOpen : proposed.popupOpen,
261
+ current: highlightControlled ? previous.cursor.current : proposed.cursor.current,
262
+ selected: valueControlled ? previous.selection.selected : proposed.selection.selected,
263
+ anchor: valueControlled ? previous.selection.anchor : proposed.selection.anchor,
264
+ });
265
+ }
266
+ function selectedValue(state) {
267
+ return state.selection.selected[0] ?? null;
268
+ }
269
+ function controlledInputError(valueControlled, inputStateControlled, openControlled, highlightControlled, values) {
270
+ return fieldError(valueControlled, values.value !== undefined, 'value', 'combobox value')
271
+ ?? fieldError(inputStateControlled, values.inputState !== undefined, 'input-state', 'combobox input state')
272
+ ?? fieldError(openControlled, values.open !== undefined, 'open', 'combobox open state')
273
+ ?? fieldError(highlightControlled, values.highlightedValue !== undefined, 'highlighted-value', 'combobox highlight');
274
+ }
275
+ function fieldError(controlled, provided, codeName, label) {
276
+ if (controlled === provided)
277
+ return null;
278
+ return {
279
+ class: 'construction',
280
+ code: controlled ? `controlled-${codeName}-required` : `uncontrolled-${codeName}-update`,
281
+ message: controlled
282
+ ? `Controlled ${label} sync requires its external value.`
283
+ : `Uncontrolled ${label} cannot be synchronized externally.`,
284
+ };
285
+ }
286
+ //# sourceMappingURL=combobox.js.map