foldkit 0.25.0 → 0.27.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 (89) hide show
  1. package/README.md +70 -55
  2. package/dist/fieldValidation/index.d.ts +39 -29
  3. package/dist/fieldValidation/index.d.ts.map +1 -1
  4. package/dist/fieldValidation/index.js +23 -24
  5. package/dist/fieldValidation/public.d.ts +2 -2
  6. package/dist/fieldValidation/public.d.ts.map +1 -1
  7. package/dist/fieldValidation/public.js +1 -1
  8. package/dist/html/index.d.ts +2 -9
  9. package/dist/html/index.d.ts.map +1 -1
  10. package/dist/html/public.d.ts +1 -1
  11. package/dist/html/public.d.ts.map +1 -1
  12. package/dist/ui/anchor.d.ts +19 -0
  13. package/dist/ui/anchor.d.ts.map +1 -0
  14. package/dist/ui/{menu/anchor.js → anchor.js} +3 -2
  15. package/dist/ui/combobox/multi.d.ts +178 -0
  16. package/dist/ui/combobox/multi.d.ts.map +1 -0
  17. package/dist/ui/combobox/multi.js +53 -0
  18. package/dist/ui/combobox/multiPublic.d.ts +3 -0
  19. package/dist/ui/combobox/multiPublic.d.ts.map +1 -0
  20. package/dist/ui/combobox/multiPublic.js +1 -0
  21. package/dist/ui/combobox/public.d.ts +8 -0
  22. package/dist/ui/combobox/public.d.ts.map +1 -0
  23. package/dist/ui/combobox/public.js +4 -0
  24. package/dist/ui/combobox/shared.d.ts +236 -0
  25. package/dist/ui/combobox/shared.d.ts.map +1 -0
  26. package/dist/ui/combobox/shared.js +560 -0
  27. package/dist/ui/combobox/single.d.ts +183 -0
  28. package/dist/ui/combobox/single.d.ts.map +1 -0
  29. package/dist/ui/combobox/single.js +73 -0
  30. package/dist/ui/dialog/index.d.ts +3 -0
  31. package/dist/ui/dialog/index.d.ts.map +1 -1
  32. package/dist/ui/dialog/index.js +11 -0
  33. package/dist/ui/dialog/public.d.ts +1 -1
  34. package/dist/ui/dialog/public.d.ts.map +1 -1
  35. package/dist/ui/dialog/public.js +1 -1
  36. package/dist/ui/disclosure/index.d.ts +3 -0
  37. package/dist/ui/disclosure/index.d.ts.map +1 -1
  38. package/dist/ui/disclosure/index.js +11 -0
  39. package/dist/ui/disclosure/public.d.ts +1 -1
  40. package/dist/ui/disclosure/public.d.ts.map +1 -1
  41. package/dist/ui/disclosure/public.js +1 -1
  42. package/dist/ui/index.d.ts +3 -0
  43. package/dist/ui/index.d.ts.map +1 -1
  44. package/dist/ui/index.js +3 -0
  45. package/dist/ui/listbox/multi.d.ts +26 -21
  46. package/dist/ui/listbox/multi.d.ts.map +1 -1
  47. package/dist/ui/listbox/multi.js +11 -0
  48. package/dist/ui/listbox/multiPublic.d.ts +1 -1
  49. package/dist/ui/listbox/multiPublic.d.ts.map +1 -1
  50. package/dist/ui/listbox/multiPublic.js +1 -1
  51. package/dist/ui/listbox/public.d.ts +4 -3
  52. package/dist/ui/listbox/public.d.ts.map +1 -1
  53. package/dist/ui/listbox/public.js +3 -2
  54. package/dist/ui/listbox/shared.d.ts +10 -12
  55. package/dist/ui/listbox/shared.d.ts.map +1 -1
  56. package/dist/ui/listbox/shared.js +12 -6
  57. package/dist/ui/listbox/single.d.ts +26 -21
  58. package/dist/ui/listbox/single.d.ts.map +1 -1
  59. package/dist/ui/listbox/single.js +11 -0
  60. package/dist/ui/menu/index.d.ts +5 -4
  61. package/dist/ui/menu/index.d.ts.map +1 -1
  62. package/dist/ui/menu/index.js +23 -6
  63. package/dist/ui/menu/public.d.ts +3 -2
  64. package/dist/ui/menu/public.d.ts.map +1 -1
  65. package/dist/ui/menu/public.js +2 -1
  66. package/dist/ui/popover/index.d.ts +78 -0
  67. package/dist/ui/popover/index.d.ts.map +1 -0
  68. package/dist/ui/popover/index.js +248 -0
  69. package/dist/ui/popover/public.d.ts +5 -0
  70. package/dist/ui/popover/public.d.ts.map +1 -0
  71. package/dist/ui/popover/public.js +2 -0
  72. package/dist/ui/switch/index.d.ts +50 -0
  73. package/dist/ui/switch/index.d.ts.map +1 -0
  74. package/dist/ui/switch/index.js +77 -0
  75. package/dist/ui/switch/public.d.ts +3 -0
  76. package/dist/ui/switch/public.d.ts.map +1 -0
  77. package/dist/ui/switch/public.js +1 -0
  78. package/dist/ui/tabs/index.d.ts +3 -0
  79. package/dist/ui/tabs/index.d.ts.map +1 -1
  80. package/dist/ui/tabs/index.js +11 -0
  81. package/dist/ui/tabs/public.d.ts +1 -1
  82. package/dist/ui/tabs/public.d.ts.map +1 -1
  83. package/dist/ui/tabs/public.js +1 -1
  84. package/dist/ui/transition.d.ts +5 -0
  85. package/dist/ui/transition.d.ts.map +1 -0
  86. package/dist/ui/transition.js +3 -0
  87. package/package.json +14 -2
  88. package/dist/ui/menu/anchor.d.ts +0 -18
  89. package/dist/ui/menu/anchor.d.ts.map +0 -1
@@ -0,0 +1,183 @@
1
+ import { Option, Schema as S } from 'effect';
2
+ import type { Html } from '../../html';
3
+ import { type BaseInitConfig, type BaseViewConfig } from './shared';
4
+ /** Schema for the single-select combobox component's state, tracking open/closed status, active item, input value, selected item, and display text. */
5
+ export declare const Model: S.extend<S.Struct<{
6
+ id: typeof S.String;
7
+ isOpen: typeof S.Boolean;
8
+ isAnimated: typeof S.Boolean;
9
+ isModal: typeof S.Boolean;
10
+ nullable: typeof S.Boolean;
11
+ immediate: typeof S.Boolean;
12
+ selectInputOnFocus: typeof S.Boolean;
13
+ transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
14
+ maybeActiveItemIndex: S.OptionFromSelf<typeof S.Number>;
15
+ activationTrigger: S.Literal<["Pointer", "Keyboard"]>;
16
+ inputValue: typeof S.String;
17
+ maybeLastPointerPosition: S.OptionFromSelf<S.Struct<{
18
+ screenX: typeof S.Number;
19
+ screenY: typeof S.Number;
20
+ }>>;
21
+ }>, S.Struct<{
22
+ maybeSelectedItem: S.OptionFromSelf<typeof S.String>;
23
+ maybeSelectedDisplayText: S.OptionFromSelf<typeof S.String>;
24
+ }>>;
25
+ export type Model = typeof Model.Type;
26
+ /** Configuration for creating a single-select combobox model with `init`. `isAnimated` enables CSS transition coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). `selectedItem` sets the initial selection (default none). */
27
+ export type InitConfig = BaseInitConfig & Readonly<{
28
+ selectedItem?: string;
29
+ selectedDisplayText?: string;
30
+ }>;
31
+ /** Creates an initial single-select combobox model from a config. Defaults to closed with no active item, empty input, and no selection. */
32
+ export declare const init: (config: InitConfig) => Model;
33
+ /** Processes a combobox message and returns the next model and commands. Closes the combobox on selection (single-select behavior). */
34
+ export declare const update: (model: {
35
+ readonly id: string;
36
+ readonly isOpen: boolean;
37
+ readonly isAnimated: boolean;
38
+ readonly isModal: boolean;
39
+ readonly nullable: boolean;
40
+ readonly immediate: boolean;
41
+ readonly selectInputOnFocus: boolean;
42
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
43
+ readonly maybeActiveItemIndex: Option.Option<number>;
44
+ readonly activationTrigger: "Pointer" | "Keyboard";
45
+ readonly inputValue: string;
46
+ readonly maybeLastPointerPosition: Option.Option<{
47
+ readonly screenX: number;
48
+ readonly screenY: number;
49
+ }>;
50
+ } & {
51
+ readonly maybeSelectedItem: Option.Option<string>;
52
+ readonly maybeSelectedDisplayText: Option.Option<string>;
53
+ }, message: import("./shared").Message) => [{
54
+ readonly id: string;
55
+ readonly isOpen: boolean;
56
+ readonly isAnimated: boolean;
57
+ readonly isModal: boolean;
58
+ readonly nullable: boolean;
59
+ readonly immediate: boolean;
60
+ readonly selectInputOnFocus: boolean;
61
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
62
+ readonly maybeActiveItemIndex: Option.Option<number>;
63
+ readonly activationTrigger: "Pointer" | "Keyboard";
64
+ readonly inputValue: string;
65
+ readonly maybeLastPointerPosition: Option.Option<{
66
+ readonly screenX: number;
67
+ readonly screenY: number;
68
+ }>;
69
+ } & {
70
+ readonly maybeSelectedItem: Option.Option<string>;
71
+ readonly maybeSelectedDisplayText: Option.Option<string>;
72
+ }, readonly import("../../command").Command<{
73
+ readonly _tag: "Opened";
74
+ readonly maybeActiveItemIndex: Option.Option<number>;
75
+ } | {
76
+ readonly _tag: "Closed";
77
+ } | {
78
+ readonly _tag: "ClosedByTab";
79
+ } | {
80
+ readonly _tag: "ActivatedItem";
81
+ readonly activationTrigger: "Pointer" | "Keyboard";
82
+ readonly index: number;
83
+ readonly maybeImmediateSelection: Option.Option<{
84
+ readonly item: string;
85
+ readonly displayText: string;
86
+ }>;
87
+ } | {
88
+ readonly _tag: "DeactivatedItem";
89
+ } | {
90
+ readonly _tag: "SelectedItem";
91
+ readonly item: string;
92
+ readonly displayText: string;
93
+ } | {
94
+ readonly _tag: "MovedPointerOverItem";
95
+ readonly screenX: number;
96
+ readonly screenY: number;
97
+ readonly index: number;
98
+ } | {
99
+ readonly _tag: "RequestedItemClick";
100
+ readonly index: number;
101
+ } | {
102
+ readonly _tag: "NoOp";
103
+ } | {
104
+ readonly _tag: "AdvancedTransitionFrame";
105
+ } | {
106
+ readonly _tag: "EndedTransition";
107
+ } | {
108
+ readonly _tag: "DetectedInputMovement";
109
+ } | {
110
+ readonly _tag: "UpdatedInputValue";
111
+ readonly value: string;
112
+ } | {
113
+ readonly _tag: "PressedToggleButton";
114
+ }>[]];
115
+ /** Configuration for rendering a single-select combobox with `view`. */
116
+ export type ViewConfig<Message, Item extends string> = BaseViewConfig<Message, Item, Model>;
117
+ /** Renders a headless single-select combobox with keyboard navigation, selection tracking, and aria-activedescendant focus management. */
118
+ export declare const view: <Message, Item extends string>(config: Readonly<{
119
+ model: {
120
+ readonly id: string;
121
+ readonly isOpen: boolean;
122
+ readonly isAnimated: boolean;
123
+ readonly isModal: boolean;
124
+ readonly nullable: boolean;
125
+ readonly immediate: boolean;
126
+ readonly selectInputOnFocus: boolean;
127
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
128
+ readonly maybeActiveItemIndex: Option.Option<number>;
129
+ readonly activationTrigger: "Pointer" | "Keyboard";
130
+ readonly inputValue: string;
131
+ readonly maybeLastPointerPosition: Option.Option<{
132
+ readonly screenX: number;
133
+ readonly screenY: number;
134
+ }>;
135
+ } & {
136
+ readonly maybeSelectedItem: Option.Option<string>;
137
+ readonly maybeSelectedDisplayText: Option.Option<string>;
138
+ };
139
+ toMessage: (message: import("./shared").Opened | import("./shared").Closed | import("./shared").ClosedByTab | import("./shared").ActivatedItem | import("./shared").DeactivatedItem | import("./shared").SelectedItem | import("./shared").MovedPointerOverItem | import("./shared").RequestedItemClick | import("./shared").UpdatedInputValue | import("./shared").PressedToggleButton | import("./shared").NoOp) => Message;
140
+ items: readonly Item[];
141
+ itemToConfig: (item: Item, context: Readonly<{
142
+ isActive: boolean;
143
+ isDisabled: boolean;
144
+ isSelected: boolean;
145
+ }>) => Readonly<{
146
+ className: string;
147
+ content: Html;
148
+ }>;
149
+ itemToValue: (item: Item, index: number) => string;
150
+ itemToDisplayText: (item: Item, index: number) => string;
151
+ isItemDisabled?: (item: Item, index: number) => boolean;
152
+ inputClassName: string;
153
+ inputPlaceholder?: string;
154
+ itemsClassName: string;
155
+ itemsScrollClassName?: string;
156
+ backdropClassName: string;
157
+ className?: string;
158
+ inputWrapperClassName?: string;
159
+ buttonContent?: Html;
160
+ buttonClassName?: string;
161
+ formName?: string;
162
+ isDisabled?: boolean;
163
+ isInvalid?: boolean;
164
+ openOnFocus?: boolean;
165
+ itemGroupKey?: (item: Item, index: number) => string;
166
+ groupToHeading?: (groupKey: string) => Readonly<{
167
+ content: Html;
168
+ className: string;
169
+ }> | undefined;
170
+ groupClassName?: string;
171
+ separatorClassName?: string;
172
+ anchor?: Readonly<{
173
+ placement?: import("@floating-ui/dom").Placement;
174
+ gap?: number;
175
+ offset?: number;
176
+ padding?: number;
177
+ portal?: boolean;
178
+ }>;
179
+ }>) => Html;
180
+ /** Creates a memoized single-select combobox view. Static config is captured in a closure;
181
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
182
+ export declare const lazy: <Message, Item extends string>(staticConfig: Omit<ViewConfig<Message, Item>, "model" | "toMessage">) => ((model: Model, toMessage: BaseViewConfig<Message, Item, Model>["toMessage"]) => Html);
183
+ //# sourceMappingURL=single.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../../src/ui/combobox/single.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,IAAI,CAAC,EAAQ,MAAM,QAAQ,CAAA;AAEzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAGtC,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAKpB,MAAM,UAAU,CAAA;AAIjB,uJAAuJ;AACvJ,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;GAOjB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,8RAA8R;AAC9R,MAAM,MAAM,UAAU,GAAG,cAAc,GACrC,QAAQ,CAAC;IACP,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAC,CAAA;AAEJ,4IAA4I;AAC5I,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAMxC,CAAA;AAIF,uIAAuI;AACvI,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqDjB,CAAA;AAIF,wEAAwE;AACxE,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,SAAS,MAAM,IAAI,cAAc,CACnE,OAAO,EACP,IAAI,EACJ,KAAK,CACN,CAAA;AAED,0IAA0I;AAC1I,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAOf,CAAA;AAEF;6EAC6E;AAC7E,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,IAAI,SAAS,MAAM,EAC/C,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC,KACnE,CAAC,CACF,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KACzD,IAAI,CAgBR,CAAA"}
@@ -0,0 +1,73 @@
1
+ import { Array, Option, Schema as S, pipe } from 'effect';
2
+ import { createLazy } from '../../html/lazy';
3
+ import { evo } from '../../struct';
4
+ import { BaseModel, baseInit, closedBaseModel, makeUpdate, makeView, } from './shared';
5
+ // MODEL
6
+ /** Schema for the single-select combobox component's state, tracking open/closed status, active item, input value, selected item, and display text. */
7
+ export const Model = BaseModel.pipe(S.extend(S.Struct({
8
+ maybeSelectedItem: S.OptionFromSelf(S.String),
9
+ maybeSelectedDisplayText: S.OptionFromSelf(S.String),
10
+ })));
11
+ /** Creates an initial single-select combobox model from a config. Defaults to closed with no active item, empty input, and no selection. */
12
+ export const init = (config) => ({
13
+ ...baseInit(config),
14
+ maybeSelectedItem: Option.fromNullable(config.selectedItem),
15
+ maybeSelectedDisplayText: Option.fromNullable(config.selectedDisplayText ?? config.selectedItem),
16
+ });
17
+ // UPDATE
18
+ /** Processes a combobox message and returns the next model and commands. Closes the combobox on selection (single-select behavior). */
19
+ export const update = makeUpdate({
20
+ handleClose: model => {
21
+ if (model.nullable && model.inputValue === '') {
22
+ return evo(closedBaseModel(model), {
23
+ maybeSelectedItem: () => Option.none(),
24
+ maybeSelectedDisplayText: () => Option.none(),
25
+ inputValue: () => '',
26
+ });
27
+ }
28
+ return evo(closedBaseModel(model), {
29
+ inputValue: () => Option.getOrElse(model.maybeSelectedDisplayText, () => ''),
30
+ });
31
+ },
32
+ handleSelectedItem: (model, item, displayText, context) => {
33
+ const isAlreadySelected = Option.exists(model.maybeSelectedItem, selectedItem => selectedItem === item);
34
+ const nextModel = model.nullable && isAlreadySelected
35
+ ? evo(closedBaseModel(model), {
36
+ inputValue: () => '',
37
+ maybeSelectedItem: () => Option.none(),
38
+ maybeSelectedDisplayText: () => Option.none(),
39
+ })
40
+ : evo(closedBaseModel(model), {
41
+ inputValue: () => displayText,
42
+ maybeSelectedItem: () => Option.some(item),
43
+ maybeSelectedDisplayText: () => Option.some(displayText),
44
+ });
45
+ return [
46
+ nextModel,
47
+ pipe(Array.getSomes([
48
+ context.maybeNextFrame,
49
+ context.maybeUnlockScroll,
50
+ context.maybeRestoreInert,
51
+ ]), Array.prepend(context.focusInput)),
52
+ ];
53
+ },
54
+ handleImmediateActivation: (model, item, displayText) => evo(model, {
55
+ maybeSelectedItem: () => Option.some(item),
56
+ maybeSelectedDisplayText: () => Option.some(displayText),
57
+ }),
58
+ });
59
+ /** Renders a headless single-select combobox with keyboard navigation, selection tracking, and aria-activedescendant focus management. */
60
+ export const view = makeView({
61
+ isItemSelected: (model, itemValue) => Option.exists(model.maybeSelectedItem, selectedItem => selectedItem === itemValue),
62
+ ariaMultiSelectable: false,
63
+ });
64
+ /** Creates a memoized single-select combobox view. Static config is captured in a closure;
65
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
66
+ export const lazy = (staticConfig) => {
67
+ const lazyView = createLazy();
68
+ return (model, toMessage) => lazyView((currentModel, currentToMessage) => view({
69
+ ...staticConfig,
70
+ model: currentModel,
71
+ toMessage: currentToMessage,
72
+ }), [model, toMessage]);
73
+ };
@@ -43,4 +43,7 @@ export type ViewConfig<Message> = Readonly<{
43
43
  }>;
44
44
  /** Renders a headless dialog component backed by the native `<dialog>` element with `showModal()`. */
45
45
  export declare const view: <Message>(config: ViewConfig<Message>) => Html;
46
+ /** Creates a memoized dialog view. Static config is captured in a closure;
47
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
48
+ export declare const lazy: <Message>(staticConfig: Omit<ViewConfig<Message>, "model" | "toMessage">) => ((model: Model, toMessage: ViewConfig<Message>["toMessage"]) => Html);
46
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/dialog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAOtC,8FAA8F;AAC9F,eAAO,MAAM,KAAK;;;EAGhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,wEAAwE;AACxE,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,wHAAwH;AACxH,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,oHAAoH;AACpH,eAAO,MAAM,IAAI,yDAAY,CAAA;AAE7B,8DAA8D;AAC9D,eAAO,MAAM,OAAO,0LAAgC,CAAA;AAEpD,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;AAEnC,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAC,CAAA;AAEF,yEAAyE;AACzE,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAMF,0EAA0E;AAC1E,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CA4BvC,CAAA;AAIH,iGAAiG;AACjG,eAAO,MAAM,OAAO,GAAI,OAAO,KAAK,KAAG,MAA6B,CAAA;AAEpE,wGAAwG;AACxG,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,KAAG,MAAmC,CAAA;AAEhF,wDAAwD;AACxD,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAA;IAC9C,YAAY,EAAE,IAAI,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEF,sGAAsG;AACtG,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,QAAQ,UAAU,CAAC,OAAO,CAAC,KAAG,IA6C3D,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/dialog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAQtC,8FAA8F;AAC9F,eAAO,MAAM,KAAK;;;EAGhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,wEAAwE;AACxE,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,wHAAwH;AACxH,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,oHAAoH;AACpH,eAAO,MAAM,IAAI,yDAAY,CAAA;AAE7B,8DAA8D;AAC9D,eAAO,MAAM,OAAO,0LAAgC,CAAA;AAEpD,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;AAEnC,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAC,CAAA;AAEF,yEAAyE;AACzE,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAMF,0EAA0E;AAC1E,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CA4BvC,CAAA;AAIH,iGAAiG;AACjG,eAAO,MAAM,OAAO,GAAI,OAAO,KAAK,KAAG,MAA6B,CAAA;AAEpE,wGAAwG;AACxG,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,KAAG,MAAmC,CAAA;AAEhF,wDAAwD;AACxD,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAA;IAC9C,YAAY,EAAE,IAAI,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEF,sGAAsG;AACtG,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,QAAQ,UAAU,CAAC,OAAO,CAAC,KAAG,IA6C3D,CAAA;AAED;6EAC6E;AAC7E,eAAO,MAAM,IAAI,GAAI,OAAO,EAC1B,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC,KAC7D,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,CAgBtE,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { Effect, Match as M, Option, Schema as S } from 'effect';
2
2
  import { html } from '../../html';
3
+ import { createLazy } from '../../html/lazy';
3
4
  import { m } from '../../message';
4
5
  import { evo } from '../../struct';
5
6
  import * as Task from '../../task';
@@ -59,3 +60,13 @@ export const view = (config) => {
59
60
  const content = isOpen ? [backdrop, panel] : [];
60
61
  return keyed('dialog')(id, dialogAttributes, content);
61
62
  };
63
+ /** Creates a memoized dialog view. Static config is captured in a closure;
64
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
65
+ export const lazy = (staticConfig) => {
66
+ const lazyView = createLazy();
67
+ return (model, toMessage) => lazyView((currentModel, currentToMessage) => view({
68
+ ...staticConfig,
69
+ model: currentModel,
70
+ toMessage: currentToMessage,
71
+ }), [model, toMessage]);
72
+ };
@@ -1,3 +1,3 @@
1
- export { init, update, view, titleId, descriptionId, Model, Message, Opened, Closed, NoOp, } from './index';
1
+ export { init, update, view, lazy, titleId, descriptionId, Model, Message, Opened, Closed, NoOp, } from './index';
2
2
  export type { InitConfig, ViewConfig } from './index';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/dialog/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,OAAO,EACP,aAAa,EACb,KAAK,EACL,OAAO,EACP,MAAM,EACN,MAAM,EACN,IAAI,GACL,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/dialog/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,aAAa,EACb,KAAK,EACL,OAAO,EACP,MAAM,EACN,MAAM,EACN,IAAI,GACL,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
@@ -1 +1 @@
1
- export { init, update, view, titleId, descriptionId, Model, Message, Opened, Closed, NoOp, } from './index';
1
+ export { init, update, view, lazy, titleId, descriptionId, Model, Message, Opened, Closed, NoOp, } from './index';
@@ -44,4 +44,7 @@ export type ViewConfig<Message> = Readonly<{
44
44
  }>;
45
45
  /** Renders a headless disclosure component with accessible ARIA attributes and keyboard support. */
46
46
  export declare const view: <Message>(config: ViewConfig<Message>) => Html;
47
+ /** Creates a memoized disclosure view. Static config is captured in a closure;
48
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
49
+ export declare const lazy: <Message>(staticConfig: Omit<ViewConfig<Message>, "model" | "toMessage">) => ((model: Model, toMessage: ViewConfig<Message>["toMessage"]) => Html);
47
50
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAO/C,kGAAkG;AAClG,eAAO,MAAM,KAAK;;;EAGhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,iFAAiF;AACjF,eAAO,MAAM,OAAO,4DAAe,CAAA;AACnC,gFAAgF;AAChF,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,kGAAkG;AAClG,eAAO,MAAM,IAAI,yDAAY,CAAA;AAE7B,kEAAkE;AAClE,eAAO,MAAM,OAAO,2LAAiC,CAAA;AAErD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AACzC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;AAEnC,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAC,CAAA;AAEF,6EAA6E;AAC7E,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAUF,8EAA8E;AAC9E,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CA+BvC,CAAA;AAIH,4DAA4D;AAC5D,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,KAAK,OAAO,CAAA;IACxD,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,IAAI,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,IAAI,CAAA;IAClB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEF,oGAAoG;AACpG,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,QAAQ,UAAU,CAAC,OAAO,CAAC,KAAG,IAyF3D,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAQ/C,kGAAkG;AAClG,eAAO,MAAM,KAAK;;;EAGhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,iFAAiF;AACjF,eAAO,MAAM,OAAO,4DAAe,CAAA;AACnC,gFAAgF;AAChF,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,kGAAkG;AAClG,eAAO,MAAM,IAAI,yDAAY,CAAA;AAE7B,kEAAkE;AAClE,eAAO,MAAM,OAAO,2LAAiC,CAAA;AAErD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AACzC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,CAAA;AAEnC,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAC,CAAA;AAEF,6EAA6E;AAC7E,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAUF,8EAA8E;AAC9E,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CA+BvC,CAAA;AAIH,4DAA4D;AAC5D,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,KAAK,OAAO,CAAA;IACxD,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,IAAI,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,IAAI,CAAA;IAClB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEF,oGAAoG;AACpG,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,QAAQ,UAAU,CAAC,OAAO,CAAC,KAAG,IAyF3D,CAAA;AAED;6EAC6E;AAC7E,eAAO,MAAM,IAAI,GAAI,OAAO,EAC1B,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC,KAC7D,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,CAgBtE,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { Effect, Match as M, Option, Schema as S } from 'effect';
2
2
  import { html } from '../../html';
3
+ import { createLazy } from '../../html/lazy';
3
4
  import { m } from '../../message';
4
5
  import { evo } from '../../struct';
5
6
  import * as Task from '../../task';
@@ -86,3 +87,13 @@ export const view = (config) => {
86
87
  panel,
87
88
  ]);
88
89
  };
90
+ /** Creates a memoized disclosure view. Static config is captured in a closure;
91
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
92
+ export const lazy = (staticConfig) => {
93
+ const lazyView = createLazy();
94
+ return (model, toMessage) => lazyView((currentModel, currentToMessage) => view({
95
+ ...staticConfig,
96
+ model: currentModel,
97
+ toMessage: currentToMessage,
98
+ }), [model, toMessage]);
99
+ };
@@ -1,3 +1,3 @@
1
- export { init, update, view, Model, Message } from './index';
1
+ export { init, update, view, lazy, Model, Message } from './index';
2
2
  export type { Toggled, Closed, NoOp, InitConfig, ViewConfig } from './index';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAE5D,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAElE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
@@ -1 +1 @@
1
- export { init, update, view, Model, Message } from './index';
1
+ export { init, update, view, lazy, Model, Message } from './index';
@@ -1,6 +1,9 @@
1
+ export * as Combobox from './combobox/public';
1
2
  export * as Dialog from './dialog/public';
2
3
  export * as Disclosure from './disclosure/public';
3
4
  export * as Listbox from './listbox/public';
4
5
  export * as Menu from './menu/public';
6
+ export * as Popover from './popover/public';
7
+ export * as Switch from './switch/public';
5
8
  export * as Tabs from './tabs/public';
6
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA"}
package/dist/ui/index.js CHANGED
@@ -1,5 +1,8 @@
1
+ export * as Combobox from './combobox/public';
1
2
  export * as Dialog from './dialog/public';
2
3
  export * as Disclosure from './disclosure/public';
3
4
  export * as Listbox from './listbox/public';
4
5
  export * as Menu from './menu/public';
6
+ export * as Popover from './popover/public';
7
+ export * as Switch from './switch/public';
5
8
  export * as Tabs from './tabs/public';
@@ -1,4 +1,5 @@
1
1
  import { Option, Schema as S } from 'effect';
2
+ import type { Html } from '../../html';
2
3
  import { type BaseInitConfig, type BaseViewConfig } from './shared';
3
4
  /** Schema for the multi-select listbox component's state, tracking open/closed status, active item, selected items, activation trigger, and typeahead search. */
4
5
  export declare const Model: S.extend<S.Struct<{
@@ -33,16 +34,16 @@ export declare const update: (model: {
33
34
  readonly isOpen: boolean;
34
35
  readonly isAnimated: boolean;
35
36
  readonly isModal: boolean;
36
- readonly orientation: "Vertical" | "Horizontal";
37
37
  readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
38
38
  readonly maybeActiveItemIndex: Option.Option<number>;
39
39
  readonly activationTrigger: "Pointer" | "Keyboard";
40
- readonly searchQuery: string;
41
- readonly searchVersion: number;
42
40
  readonly maybeLastPointerPosition: Option.Option<{
43
41
  readonly screenX: number;
44
42
  readonly screenY: number;
45
43
  }>;
44
+ readonly orientation: "Vertical" | "Horizontal";
45
+ readonly searchQuery: string;
46
+ readonly searchVersion: number;
46
47
  readonly maybeLastButtonPointerType: Option.Option<string>;
47
48
  } & {
48
49
  readonly selectedItems: readonly string[];
@@ -51,34 +52,38 @@ export declare const update: (model: {
51
52
  readonly isOpen: boolean;
52
53
  readonly isAnimated: boolean;
53
54
  readonly isModal: boolean;
54
- readonly orientation: "Vertical" | "Horizontal";
55
55
  readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
56
56
  readonly maybeActiveItemIndex: Option.Option<number>;
57
57
  readonly activationTrigger: "Pointer" | "Keyboard";
58
- readonly searchQuery: string;
59
- readonly searchVersion: number;
60
58
  readonly maybeLastPointerPosition: Option.Option<{
61
59
  readonly screenX: number;
62
60
  readonly screenY: number;
63
61
  }>;
62
+ readonly orientation: "Vertical" | "Horizontal";
63
+ readonly searchQuery: string;
64
+ readonly searchVersion: number;
64
65
  readonly maybeLastButtonPointerType: Option.Option<string>;
65
66
  } & {
66
67
  readonly selectedItems: readonly string[];
67
68
  }, readonly import("../../command").Command<{
68
69
  readonly _tag: "Closed";
70
+ } | {
71
+ readonly _tag: "ClosedByTab";
72
+ } | {
73
+ readonly _tag: "DeactivatedItem";
69
74
  } | {
70
75
  readonly _tag: "NoOp";
76
+ } | {
77
+ readonly _tag: "AdvancedTransitionFrame";
78
+ } | {
79
+ readonly _tag: "EndedTransition";
71
80
  } | {
72
81
  readonly _tag: "Opened";
73
82
  readonly maybeActiveItemIndex: Option.Option<number>;
74
- } | {
75
- readonly _tag: "ClosedByTab";
76
83
  } | {
77
84
  readonly _tag: "ActivatedItem";
78
85
  readonly activationTrigger: "Pointer" | "Keyboard";
79
86
  readonly index: number;
80
- } | {
81
- readonly _tag: "DeactivatedItem";
82
87
  } | {
83
88
  readonly _tag: "SelectedItem";
84
89
  readonly item: string;
@@ -97,10 +102,6 @@ export declare const update: (model: {
97
102
  } | {
98
103
  readonly _tag: "ClearedSearch";
99
104
  readonly version: number;
100
- } | {
101
- readonly _tag: "AdvancedTransitionFrame";
102
- } | {
103
- readonly _tag: "EndedTransition";
104
105
  } | {
105
106
  readonly _tag: "DetectedButtonMovement";
106
107
  } | {
@@ -117,16 +118,16 @@ export declare const view: <Message, Item>(config: Readonly<{
117
118
  readonly isOpen: boolean;
118
119
  readonly isAnimated: boolean;
119
120
  readonly isModal: boolean;
120
- readonly orientation: "Vertical" | "Horizontal";
121
121
  readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
122
122
  readonly maybeActiveItemIndex: Option.Option<number>;
123
123
  readonly activationTrigger: "Pointer" | "Keyboard";
124
- readonly searchQuery: string;
125
- readonly searchVersion: number;
126
124
  readonly maybeLastPointerPosition: Option.Option<{
127
125
  readonly screenX: number;
128
126
  readonly screenY: number;
129
127
  }>;
128
+ readonly orientation: "Vertical" | "Horizontal";
129
+ readonly searchQuery: string;
130
+ readonly searchVersion: number;
130
131
  readonly maybeLastButtonPointerType: Option.Option<string>;
131
132
  } & {
132
133
  readonly selectedItems: readonly string[];
@@ -139,20 +140,21 @@ export declare const view: <Message, Item>(config: Readonly<{
139
140
  isSelected: boolean;
140
141
  }>) => Readonly<{
141
142
  className: string;
142
- content: import("../../html").Html;
143
+ content: Html;
143
144
  }>;
144
145
  isItemDisabled?: (item: Item, index: number) => boolean;
145
146
  itemToSearchText?: (item: Item, index: number) => string;
146
147
  itemToValue?: (item: Item) => string;
147
148
  isButtonDisabled?: boolean;
148
- buttonContent: import("../../html").Html;
149
+ buttonContent: Html;
149
150
  buttonClassName: string;
150
151
  itemsClassName: string;
152
+ itemsScrollClassName?: string;
151
153
  backdropClassName: string;
152
154
  className?: string;
153
155
  itemGroupKey?: (item: Item, index: number) => string;
154
156
  groupToHeading?: (groupKey: string) => Readonly<{
155
- content: import("../../html").Html;
157
+ content: Html;
156
158
  className: string;
157
159
  }> | undefined;
158
160
  groupClassName?: string;
@@ -168,5 +170,8 @@ export declare const view: <Message, Item>(config: Readonly<{
168
170
  form?: string;
169
171
  isDisabled?: boolean;
170
172
  isInvalid?: boolean;
171
- }>) => import("../../html").Html;
173
+ }>) => Html;
174
+ /** Creates a memoized multi-select listbox view. Static config is captured in a closure;
175
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
176
+ export declare const lazy: <Message, Item>(staticConfig: Omit<ViewConfig<Message, Item>, "model" | "toMessage">) => ((model: Model, toMessage: BaseViewConfig<Message, Item, Model>["toMessage"]) => Html);
172
177
  //# sourceMappingURL=multi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/multi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,IAAI,CAAC,EAAQ,MAAM,QAAQ,CAAA;AAGzD,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAIpB,MAAM,UAAU,CAAA;AAIjB,iKAAiK;AACjK,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;GAEjB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,6RAA6R;AAC7R,MAAM,MAAM,UAAU,GAAG,cAAc,GACrC,QAAQ,CAAC;IACP,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACtC,CAAC,CAAA;AAEJ,4HAA4H;AAC5H,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAIF,wJAAwJ;AACxJ,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAMjB,CAAA;AAIF,sEAAsE;AACtE,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;AAE5E,0JAA0J;AAC1J,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAYf,CAAA"}
1
+ {"version":3,"file":"multi.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/multi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,MAAM,IAAI,CAAC,EAAQ,MAAM,QAAQ,CAAA;AAEzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAGtC,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAIpB,MAAM,UAAU,CAAA;AAIjB,iKAAiK;AACjK,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;GAEjB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,6RAA6R;AAC7R,MAAM,MAAM,UAAU,GAAG,cAAc,GACrC,QAAQ,CAAC;IACP,aAAa,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACtC,CAAC,CAAA;AAEJ,4HAA4H;AAC5H,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAGxC,CAAA;AAIF,wJAAwJ;AACxJ,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAMjB,CAAA;AAIF,sEAAsE;AACtE,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;AAE5E,0JAA0J;AAC1J,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAYf,CAAA;AAEF;6EAC6E;AAC7E,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,IAAI,EAChC,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC,KACnE,CAAC,CACF,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC,KACzD,IAAI,CAgBR,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { Array, Option, Schema as S, pipe } from 'effect';
2
+ import { createLazy } from '../../html/lazy';
2
3
  import { evo } from '../../struct';
3
4
  import { BaseModel, baseInit, makeUpdate, makeView, } from './shared';
4
5
  // MODEL
@@ -23,3 +24,13 @@ export const view = makeView({
23
24
  selectedItemIndex: (model, items, itemToValue) => pipe(model.selectedItems, Array.head, Option.flatMap(selectedItem => Array.findFirstIndex(items, item => itemToValue(item) === selectedItem))),
24
25
  ariaMultiSelectable: true,
25
26
  });
27
+ /** Creates a memoized multi-select listbox view. Static config is captured in a closure;
28
+ * only `model` and `toMessage` are compared per render via `createLazy`. */
29
+ export const lazy = (staticConfig) => {
30
+ const lazyView = createLazy();
31
+ return (model, toMessage) => lazyView((currentModel, currentToMessage) => view({
32
+ ...staticConfig,
33
+ model: currentModel,
34
+ toMessage: currentToMessage,
35
+ }), [model, toMessage]);
36
+ };
@@ -1,3 +1,3 @@
1
- export { init, update, view, Model } from './multi';
1
+ export { init, update, view, lazy, Model } from './multi';
2
2
  export type { InitConfig, ViewConfig } from './multi';
3
3
  //# sourceMappingURL=multiPublic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"multiPublic.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/multiPublic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AACnD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"multiPublic.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/multiPublic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AACzD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
@@ -1 +1 @@
1
- export { init, update, view, Model } from './multi';
1
+ export { init, update, view, lazy, Model } from './multi';
@@ -1,7 +1,8 @@
1
- export { init, update, view, Model } from './single';
2
- export { Message, TransitionState, Orientation } from './shared';
1
+ export { init, update, view, lazy, Model } from './single';
2
+ export { Message, Orientation } from './shared';
3
+ export { TransitionState } from '../transition';
3
4
  export type { ActivationTrigger, Opened, Closed, ClosedByTab, ActivatedItem, DeactivatedItem, SelectedItem, MovedPointerOverItem, Searched, ClearedSearch, NoOp, AdvancedTransitionFrame, EndedTransition, ItemConfig, GroupHeading, } from './shared';
4
5
  export type { InitConfig, ViewConfig } from './single';
5
- export type { AnchorConfig } from '../menu/anchor';
6
+ export type { AnchorConfig } from '../anchor';
6
7
  export * as Multi from './multiPublic';
7
8
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAEpD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEhE,YAAY,EACV,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,WAAW,EACX,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,QAAQ,EACR,aAAa,EACb,IAAI,EACJ,uBAAuB,EACvB,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,UAAU,CAAA;AAEjB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEtD,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,KAAK,KAAK,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/listbox/public.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAE1D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,YAAY,EACV,iBAAiB,EACjB,MAAM,EACN,MAAM,EACN,WAAW,EACX,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,QAAQ,EACR,aAAa,EACb,IAAI,EACJ,uBAAuB,EACvB,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,UAAU,CAAA;AAEjB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEtD,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,OAAO,KAAK,KAAK,MAAM,eAAe,CAAA"}
@@ -1,3 +1,4 @@
1
- export { init, update, view, Model } from './single';
2
- export { Message, TransitionState, Orientation } from './shared';
1
+ export { init, update, view, lazy, Model } from './single';
2
+ export { Message, Orientation } from './shared';
3
+ export { TransitionState } from '../transition';
3
4
  export * as Multi from './multiPublic';