@k2b/ui 0.31.0 → 0.33.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 (209) hide show
  1. package/dist/base.css +2 -0
  2. package/dist/browser/actions/Dropdown.js +159 -99
  3. package/dist/browser/actions/Dropdown.js.map +1 -1
  4. package/dist/browser/actions/FilterChip.js +113 -56
  5. package/dist/browser/actions/FilterChip.js.map +1 -1
  6. package/dist/browser/actions/ViewTabs.js +8 -0
  7. package/dist/browser/actions/ViewTabs.js.map +1 -1
  8. package/dist/browser/actions/filter-messages.js +26 -2
  9. package/dist/browser/actions/filter-messages.js.map +1 -1
  10. package/dist/browser/actions/menu-rows.js +23 -3
  11. package/dist/browser/actions/menu-rows.js.map +1 -1
  12. package/dist/browser/actions/menu-sheet.js +2 -7
  13. package/dist/browser/actions/menu-sheet.js.map +1 -1
  14. package/dist/browser/chat/ChatComposer.js +480 -403
  15. package/dist/browser/chat/ChatComposer.js.map +1 -1
  16. package/dist/browser/chat/chat-messages.js +14 -0
  17. package/dist/browser/chat/chat-messages.js.map +1 -1
  18. package/dist/browser/chat/index.js.map +1 -1
  19. package/dist/browser/content/Calendar.js +39 -29
  20. package/dist/browser/content/Calendar.js.map +1 -1
  21. package/dist/browser/content/CalendarDayView.js +159 -165
  22. package/dist/browser/content/CalendarDayView.js.map +1 -1
  23. package/dist/browser/content/Chart.js +104 -55
  24. package/dist/browser/content/Chart.js.map +1 -1
  25. package/dist/browser/content/ChartExplorer.js +5 -3
  26. package/dist/browser/content/ChartExplorer.js.map +1 -1
  27. package/dist/browser/content/MapView.js +4 -4
  28. package/dist/browser/content/MapView.js.map +1 -1
  29. package/dist/browser/content/MessageRow.js +607 -343
  30. package/dist/browser/content/MessageRow.js.map +1 -1
  31. package/dist/browser/content/ReactionBar.js +17 -0
  32. package/dist/browser/content/ReactionBar.js.map +1 -1
  33. package/dist/browser/content/chart-inspection-core.js +4 -1
  34. package/dist/browser/content/chart-inspection-core.js.map +1 -1
  35. package/dist/browser/content/code-highlight.js +66 -0
  36. package/dist/browser/content/code-highlight.js.map +1 -1
  37. package/dist/browser/content/index.js +2 -1
  38. package/dist/browser/content/index.js.map +1 -1
  39. package/dist/browser/content/map-view-live.js +47 -10
  40. package/dist/browser/content/map-view-live.js.map +1 -1
  41. package/dist/browser/content/map-view-types.js.map +1 -1
  42. package/dist/browser/feedback/dialog-core.js +6 -0
  43. package/dist/browser/feedback/dialog-core.js.map +1 -1
  44. package/dist/browser/inputs/AutocompleteEditor.js +167 -104
  45. package/dist/browser/inputs/AutocompleteEditor.js.map +1 -1
  46. package/dist/browser/inputs/RichSelect.js +1474 -0
  47. package/dist/browser/inputs/RichSelect.js.map +1 -0
  48. package/dist/browser/inputs/TextInput.js +99 -61
  49. package/dist/browser/inputs/TextInput.js.map +1 -1
  50. package/dist/browser/inputs/choice.js +19 -8
  51. package/dist/browser/inputs/choice.js.map +1 -1
  52. package/dist/browser/inputs/index.js +1 -0
  53. package/dist/browser/inputs/index.js.map +1 -1
  54. package/dist/browser/inputs/rich-select-messages.js +46 -0
  55. package/dist/browser/inputs/rich-select-messages.js.map +1 -0
  56. package/dist/browser/intl/shortcut-messages.js +4 -0
  57. package/dist/browser/intl/shortcut-messages.js.map +1 -1
  58. package/dist/browser/intl/shortcut.js +4 -0
  59. package/dist/browser/intl/shortcut.js.map +1 -1
  60. package/dist/browser/layout/AppWorkspace.js +624 -565
  61. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  62. package/dist/browser/layout/DetailPanel.js +10 -1
  63. package/dist/browser/layout/DetailPanel.js.map +1 -1
  64. package/dist/browser/layout/MobileShell.js +213 -38
  65. package/dist/browser/layout/MobileShell.js.map +1 -1
  66. package/dist/browser/layout/Navigation.js +14 -5
  67. package/dist/browser/layout/Navigation.js.map +1 -1
  68. package/dist/browser/layout/PageTitle.js +9 -3
  69. package/dist/browser/layout/PageTitle.js.map +1 -1
  70. package/dist/browser/layout/ResizeSeparator.js +8 -2
  71. package/dist/browser/layout/ResizeSeparator.js.map +1 -1
  72. package/dist/browser/layout/app-workspace-controller.js +192 -31
  73. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  74. package/dist/browser/layout/index.js +1 -0
  75. package/dist/browser/layout/index.js.map +1 -1
  76. package/dist/browser/layout/navigation-model.js.map +1 -1
  77. package/dist/browser/layout/resize-separator.js +25 -1
  78. package/dist/browser/layout/resize-separator.js.map +1 -1
  79. package/dist/browser/layout/scroll-fade.js +32 -5
  80. package/dist/browser/layout/scroll-fade.js.map +1 -1
  81. package/dist/browser/surfaces/NoticeCard.js +46 -30
  82. package/dist/browser/surfaces/NoticeCard.js.map +1 -1
  83. package/dist/browser/surfaces/Skeleton.js +14 -0
  84. package/dist/browser/surfaces/Skeleton.js.map +1 -0
  85. package/dist/browser/surfaces/index.js +1 -0
  86. package/dist/browser/surfaces/index.js.map +1 -1
  87. package/dist/browser/surfaces/resource-messages.js +2 -2
  88. package/dist/browser/surfaces/resource-messages.js.map +1 -1
  89. package/dist/ssr/actions/Dropdown.js +51 -27
  90. package/dist/ssr/actions/Dropdown.js.map +1 -1
  91. package/dist/ssr/actions/FilterChip.js +67 -16
  92. package/dist/ssr/actions/FilterChip.js.map +1 -1
  93. package/dist/ssr/actions/ViewTabs.js +8 -0
  94. package/dist/ssr/actions/ViewTabs.js.map +1 -1
  95. package/dist/ssr/actions/filter-messages.js +26 -2
  96. package/dist/ssr/actions/filter-messages.js.map +1 -1
  97. package/dist/ssr/actions/menu-rows.js +23 -3
  98. package/dist/ssr/actions/menu-rows.js.map +1 -1
  99. package/dist/ssr/actions/menu-sheet.js +2 -7
  100. package/dist/ssr/actions/menu-sheet.js.map +1 -1
  101. package/dist/ssr/chat/ChatComposer.js +96 -67
  102. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  103. package/dist/ssr/chat/chat-messages.js +14 -0
  104. package/dist/ssr/chat/chat-messages.js.map +1 -1
  105. package/dist/ssr/chat/index.js.map +1 -1
  106. package/dist/ssr/content/Calendar.js +40 -31
  107. package/dist/ssr/content/Calendar.js.map +1 -1
  108. package/dist/ssr/content/CalendarDayView.js +40 -48
  109. package/dist/ssr/content/CalendarDayView.js.map +1 -1
  110. package/dist/ssr/content/Chart.js +27 -7
  111. package/dist/ssr/content/Chart.js.map +1 -1
  112. package/dist/ssr/content/ChartExplorer.js +5 -3
  113. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  114. package/dist/ssr/content/MapView.js +4 -4
  115. package/dist/ssr/content/MapView.js.map +1 -1
  116. package/dist/ssr/content/MessageRow.js +264 -91
  117. package/dist/ssr/content/MessageRow.js.map +1 -1
  118. package/dist/ssr/content/ReactionBar.js +17 -0
  119. package/dist/ssr/content/ReactionBar.js.map +1 -1
  120. package/dist/ssr/content/chart-inspection-core.js +4 -1
  121. package/dist/ssr/content/chart-inspection-core.js.map +1 -1
  122. package/dist/ssr/content/code-highlight.js +66 -0
  123. package/dist/ssr/content/code-highlight.js.map +1 -1
  124. package/dist/ssr/content/index.js +2 -1
  125. package/dist/ssr/content/index.js.map +1 -1
  126. package/dist/ssr/content/map-view-types.js.map +1 -1
  127. package/dist/ssr/feedback/dialog-core.js +6 -0
  128. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  129. package/dist/ssr/inputs/AutocompleteEditor.js +64 -24
  130. package/dist/ssr/inputs/AutocompleteEditor.js.map +1 -1
  131. package/dist/ssr/inputs/RichSelect.js +950 -0
  132. package/dist/ssr/inputs/RichSelect.js.map +1 -0
  133. package/dist/ssr/inputs/TextInput.js +44 -17
  134. package/dist/ssr/inputs/TextInput.js.map +1 -1
  135. package/dist/ssr/inputs/choice.js +19 -8
  136. package/dist/ssr/inputs/choice.js.map +1 -1
  137. package/dist/ssr/inputs/index.js +1 -0
  138. package/dist/ssr/inputs/index.js.map +1 -1
  139. package/dist/ssr/inputs/rich-select-messages.js +46 -0
  140. package/dist/ssr/inputs/rich-select-messages.js.map +1 -0
  141. package/dist/ssr/intl/shortcut-messages.js +4 -0
  142. package/dist/ssr/intl/shortcut-messages.js.map +1 -1
  143. package/dist/ssr/intl/shortcut.js +4 -0
  144. package/dist/ssr/intl/shortcut.js.map +1 -1
  145. package/dist/ssr/layout/AppWorkspace.js +166 -125
  146. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  147. package/dist/ssr/layout/DetailPanel.js +1 -1
  148. package/dist/ssr/layout/DetailPanel.js.map +1 -1
  149. package/dist/ssr/layout/MobileShell.js +100 -20
  150. package/dist/ssr/layout/MobileShell.js.map +1 -1
  151. package/dist/ssr/layout/Navigation.js +1 -1
  152. package/dist/ssr/layout/Navigation.js.map +1 -1
  153. package/dist/ssr/layout/PageTitle.js +9 -3
  154. package/dist/ssr/layout/PageTitle.js.map +1 -1
  155. package/dist/ssr/layout/ResizeSeparator.js +4 -1
  156. package/dist/ssr/layout/ResizeSeparator.js.map +1 -1
  157. package/dist/ssr/layout/app-workspace-controller.js +192 -31
  158. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  159. package/dist/ssr/layout/index.js +1 -0
  160. package/dist/ssr/layout/index.js.map +1 -1
  161. package/dist/ssr/layout/navigation-model.js.map +1 -1
  162. package/dist/ssr/layout/resize-separator.js +25 -1
  163. package/dist/ssr/layout/resize-separator.js.map +1 -1
  164. package/dist/ssr/layout/scroll-fade.js +32 -5
  165. package/dist/ssr/layout/scroll-fade.js.map +1 -1
  166. package/dist/ssr/surfaces/NoticeCard.js +21 -12
  167. package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
  168. package/dist/ssr/surfaces/Skeleton.js +8 -0
  169. package/dist/ssr/surfaces/Skeleton.js.map +1 -0
  170. package/dist/ssr/surfaces/index.js +1 -0
  171. package/dist/ssr/surfaces/index.js.map +1 -1
  172. package/dist/ssr/surfaces/resource-messages.js +2 -2
  173. package/dist/ssr/surfaces/resource-messages.js.map +1 -1
  174. package/dist/styles.css +1 -1
  175. package/dist/types/actions/Dropdown.d.ts +14 -0
  176. package/dist/types/actions/FilterChip.d.ts +11 -0
  177. package/dist/types/actions/filter-messages.d.ts +12 -0
  178. package/dist/types/actions/menu-rows.d.ts +7 -2
  179. package/dist/types/chat/ChatComposer.d.ts +13 -0
  180. package/dist/types/chat/chat-messages.d.ts +7 -0
  181. package/dist/types/chat/index.d.ts +1 -1
  182. package/dist/types/content/Calendar.d.ts +7 -0
  183. package/dist/types/content/Chart.d.ts +4 -2
  184. package/dist/types/content/ChartExplorer.d.ts +0 -1
  185. package/dist/types/content/MessageRow.d.ts +64 -2
  186. package/dist/types/content/code-highlight.d.ts +3 -1
  187. package/dist/types/content/index.d.ts +3 -2
  188. package/dist/types/content/map-view-live.d.ts +1 -1
  189. package/dist/types/content/map-view-types.d.ts +2 -0
  190. package/dist/types/feedback/dialog-core.d.ts +3 -0
  191. package/dist/types/inputs/AutocompleteEditor.d.ts +6 -1
  192. package/dist/types/inputs/RichSelect.d.ts +93 -0
  193. package/dist/types/inputs/TextInput.d.ts +5 -2
  194. package/dist/types/inputs/choice.d.ts +24 -4
  195. package/dist/types/inputs/index.d.ts +2 -0
  196. package/dist/types/inputs/rich-select-messages.d.ts +21 -0
  197. package/dist/types/intl/shortcut-messages.d.ts +2 -0
  198. package/dist/types/layout/AppWorkspace.d.ts +9 -0
  199. package/dist/types/layout/DetailPanel.d.ts +2 -0
  200. package/dist/types/layout/MobileShell.d.ts +52 -5
  201. package/dist/types/layout/app-workspace-controller.d.ts +2 -0
  202. package/dist/types/layout/index.d.ts +2 -1
  203. package/dist/types/layout/navigation-model.d.ts +2 -0
  204. package/dist/types/layout/resize-separator.d.ts +1 -0
  205. package/dist/types/layout/scroll-fade.d.ts +5 -0
  206. package/dist/types/surfaces/NoticeCard.d.ts +3 -0
  207. package/dist/types/surfaces/Skeleton.d.ts +6 -0
  208. package/dist/types/surfaces/index.d.ts +1 -0
  209. package/package.json +4 -4
@@ -44,6 +44,13 @@ export type DropdownAction = (DropdownActionBase & {
44
44
  href?: never;
45
45
  external?: never;
46
46
  });
47
+ /** A second, smaller action at the end of a row, such as "Only" beside a checkbox; it keeps the menu open. */
48
+ export type DropdownSecondaryAction = {
49
+ label: string;
50
+ /** Accessible name when the visible label alone does not say what it acts on, such as "Only Team Logistik". */
51
+ ariaLabel?: string;
52
+ action: () => void;
53
+ };
47
54
  /** Declarative radio or checkbox row for compact action menus. */
48
55
  export type DropdownChoice = DropdownActionBase & {
49
56
  action: () => void;
@@ -52,6 +59,11 @@ export type DropdownChoice = DropdownActionBase & {
52
59
  href?: string;
53
60
  closeOnSelect?: boolean;
54
61
  color?: string;
62
+ /**
63
+ * A second action at the end of the row. It shows while the row is hovered or focused, always on a touch screen,
64
+ * and keeps its place when hidden, so the row never changes width. Right and Left move between the two.
65
+ */
66
+ secondary?: DropdownSecondaryAction;
55
67
  };
56
68
  export type DropdownSection = {
57
69
  sectionLabel?: string;
@@ -60,6 +72,8 @@ export type DropdownSection = {
60
72
  * `sectionLabel`: the label names the choice above the row and for screen readers.
61
73
  */
62
74
  layout?: "row";
75
+ /** A quiet action at the end of the section label, such as "All"; it needs a `sectionLabel` and keeps the menu open. */
76
+ labelAction?: DropdownSecondaryAction;
63
77
  items: readonly (DropdownAction | DropdownChoice)[];
64
78
  };
65
79
  export type DropdownItem = DropdownAction | DropdownChoice | DropdownSection;
@@ -5,6 +5,8 @@ export type FilterChipOption = {
5
5
  label: string;
6
6
  icon?: string;
7
7
  color?: string;
8
+ /** Quiet trailing information about the option, such as a short note or a loading or warning icon with its own label. */
9
+ trailing?: JSX.Element;
8
10
  };
9
11
  export type FilterChipSection = {
10
12
  label?: string;
@@ -15,6 +17,8 @@ export type FilterChipSection = {
15
17
  * chosen option again keeps it; give the row a value in `defaultValue` so Reset keeps a choice too.
16
18
  */
17
19
  layout?: "row";
20
+ /** A labelled `multiple` section offers "All" or, once all its options are chosen, "None" beside its label. */
21
+ toggleAll?: boolean;
18
22
  };
19
23
  export type FilterChipProps = {
20
24
  label: string;
@@ -33,6 +37,13 @@ export type FilterChipProps = {
33
37
  * chips of `AppWorkspace.Head`; pass only the filter's name as `label`. The chip then grows with its value.
34
38
  */
35
39
  showValue?: boolean;
40
+ /**
41
+ * Each option of a `multiple` section offers "Only" at the end of its row: it chooses that option alone among the
42
+ * `multiple` sections and keeps the choices of single-select sections.
43
+ */
44
+ only?: boolean;
45
+ /** The trigger shows the colors of the first four chosen options before its label, as a quiet hint of what is in view. */
46
+ swatches?: boolean;
36
47
  disabled?: boolean;
37
48
  class?: string;
38
49
  };
@@ -2,6 +2,18 @@ declare const filterMessages: import("@k2b/stdlib").Catalog<{
2
2
  filterActions: string;
3
3
  filters: string;
4
4
  reset: string;
5
+ all: string;
6
+ none: string;
7
+ allOf: ({ label }: {
8
+ label: string;
9
+ }) => string;
10
+ noneOf: ({ label }: {
11
+ label: string;
12
+ }) => string;
13
+ only: string;
14
+ onlyOption: ({ label }: {
15
+ label: string;
16
+ }) => string;
5
17
  }>;
6
18
  export type FilterMessages = ReturnType<(typeof filterMessages)["resolve"]>["t"];
7
19
  /** Resolved from the inherited render locale. */
@@ -1,5 +1,10 @@
1
1
  /**
2
- * Left and Right cycle through the segments of a row section; Up and Down leave it like any item. Returns whether
3
- * the key moved focus.
2
+ * Left and Right cycle through the segments of a row section, or between a row and its secondary action; Up and Down
3
+ * leave it like any item. Returns whether the key moved focus.
4
4
  */
5
5
  export declare const focusRowSegment: (items: HTMLElement[], key: string) => boolean;
6
+ /**
7
+ * Moves Up, Down, Home, or End through the rows; a row's secondary action is no stop of its own there, so Down from
8
+ * it goes to the next row. Returns whether the key moved focus.
9
+ */
10
+ export declare const focusMenuRow: (items: HTMLElement[], key: string) => boolean;
@@ -133,6 +133,14 @@ export type ChatPasteHandler = (event: ClipboardEvent & {
133
133
  currentTarget: HTMLTextAreaElement;
134
134
  target: Element;
135
135
  }) => void;
136
+ export type ChatComposerReply = {
137
+ /** Name of the answered message's author. */
138
+ author: string;
139
+ /** Plain text of the answered message; it shows at most two lines. */
140
+ text: string;
141
+ onCancel: () => void;
142
+ onSelect?: () => void;
143
+ };
136
144
  export type ChatComposerProps = {
137
145
  value: string;
138
146
  onValueChange: (value: string) => void;
@@ -216,5 +224,10 @@ export type ChatComposerProps = {
216
224
  microphone?: ChatComposerMicrophone;
217
225
  /** One line above the field. The conversation variant always keeps its height; the default shows it only with content. */
218
226
  hint?: JSX.Element;
227
+ /**
228
+ * The message this draft answers, shown above the field on the same quiet tint as a quote in a message, with a
229
+ * button that cancels the reply. `onSelect` makes the quote a button, for example to jump to the original.
230
+ */
231
+ reply?: ChatComposerReply;
219
232
  };
220
233
  export declare function ChatComposer(props: ChatComposerProps): JSX.Element;
@@ -28,6 +28,7 @@ export declare const chatMessages: import("@k2b/stdlib").Catalog<{
28
28
  messageSent: string;
29
29
  messageNotSent: string;
30
30
  messageRetry: string;
31
+ messageDiscard: string;
31
32
  messageShowMore: string;
32
33
  messageShowLess: string;
33
34
  messageReplyTo: string;
@@ -75,6 +76,12 @@ export declare const chatMessages: import("@k2b/stdlib").Catalog<{
75
76
  couldNotLoadEarlierMessages: string;
76
77
  couldNotPostMessage: string;
77
78
  messageActions: string;
79
+ cancelReply: string;
80
+ replyingTo: string;
81
+ messageMenu: ({ author, time }: {
82
+ author: string;
83
+ time: string;
84
+ }) => string;
78
85
  messageComposer: string;
79
86
  messageInput: string;
80
87
  model: string;
@@ -7,7 +7,7 @@ import { ChatDecision, ChatMark, ChatOutcome } from "./ChatDecision";
7
7
  import { ChatActivity, ChatActivityToggle, ChatContextUsage, ChatMessage } from "./ChatPrimitives";
8
8
  import { ChatRoot } from "./ChatRoot";
9
9
  import { ChatTimeline } from "./ChatTimeline";
10
- export type { ChatCommand, ChatCommandContext, ChatCommandDraft, ChatCommandOpenResult, ChatCommandResult, ChatCommandScope, ChatCommandSearch, ChatCommandSection, ChatComposerProps, ChatFileSelection, ChatPasteHandler, } from "./ChatComposer";
10
+ export type { ChatCommand, ChatCommandContext, ChatCommandDraft, ChatCommandOpenResult, ChatCommandResult, ChatCommandScope, ChatCommandSearch, ChatCommandSection, ChatComposerProps, ChatComposerReply, ChatFileSelection, ChatPasteHandler, } from "./ChatComposer";
11
11
  export type { ChatDecisionProps, ChatMarkProps, ChatOutcomeProps, ChatPreviewExcerptProps, ChatPreviewHeaderProps, ChatPreviewLineProps, ChatPreviewPeopleProps, ChatPreviewProps, ChatPreviewReadMoreProps, ChatPreviewShowAllProps, ChatPreviewTitleProps, } from "./ChatDecision";
12
12
  export type { ChatActivityProps, ChatActivityToggleProps, ChatContextUsageProps, ChatMessageProps } from "./ChatPrimitives";
13
13
  export { formatChatTokens } from "./ChatPrimitives";
@@ -129,12 +129,19 @@ export type CalendarController = {
129
129
  export type CalendarCustomView<V extends string = string> = {
130
130
  value: V;
131
131
  label: string;
132
+ /** Days the previous and next buttons and keys move, such as 14 for a two-week list. Defaults to one day. */
133
+ days?: number;
132
134
  };
133
135
  export type CalendarProps<V extends string = never> = {
134
136
  date: Date | string;
135
137
  events: CalendarEvent[];
136
138
  view?: CalendarView | V;
137
139
  views?: CalendarView[];
140
+ /**
141
+ * `false` leaves the view switcher out of the toolbar, for a host that shows the views elsewhere, such as tabs in
142
+ * its page head. The view commands stay.
143
+ */
144
+ viewSwitcher?: boolean;
138
145
  /** Views after the built-in ones. While one is active, `children` is the body and the header pages by day. */
139
146
  customViews?: CalendarCustomView<V>[];
140
147
  /** The body of the active custom view. */
@@ -92,14 +92,16 @@ export type ChartProps = {
92
92
  /** Target when zooming in from the world view. Defaults to Europe (50, 10). */
93
93
  zoomFocus?: Pick<MapViewport, "latitude" | "longitude">;
94
94
  } : {}) & (K extends "line" ? {
95
- maxGap?: number;
95
+ /** Largest connected X distance; positive, finite, without area/errorBand fills. */ maxGap?: number;
96
+ /** Wrap the legend above the plot inside the caller's total chart height. Requires legend=true. */
97
+ legendPlacement?: "top-start";
96
98
  } : {}) & (K extends "stateTimeline" ? StateTimelineChartOptions : Omit<Parameters<(typeof charts)[K]>[0], "width" | "height" | "inspect">);
97
99
  }[ChartKind];
98
100
  /** Pure renderer options: component layout, events and inspection are configured elsewhere. */
99
101
  export type ChartRenderOptions = {
100
102
  [K in ChartKind]: Omit<Extract<ChartProps, {
101
103
  kind: K;
102
- }>, "class" | "style" | "labels" | "interactive" | "onSelect" | "selected" | "tooltip" | "cursor">;
104
+ }>, "class" | "style" | "labels" | "interactive" | "onSelect" | "selected" | "tooltip" | "cursor" | "legendPlacement">;
103
105
  }[ChartKind];
104
106
  /** Keep the fixed 28-unit bar-gauge rows inside the shared SSR/browser coordinate space. */
105
107
  export declare const chartRenderHeight: (props: ChartRenderOptions) => number;
@@ -10,7 +10,6 @@ export type ChartExplorerColumn<T> = {
10
10
  render?: (row: T) => JSX.Element;
11
11
  /**
12
12
  * Explicit comparable value. Omit to leave the column unsortable.
13
- * Returning a number also exempts the cell from spreadsheet formula guarding on copy.
14
13
  */
15
14
  sortValue?: (row: T) => string | number | null;
16
15
  align?: "left" | "center" | "right";
@@ -1,4 +1,5 @@
1
1
  import { type JSX } from "solid-js";
2
+ import { type GestureKind } from "../actions/GestureMenu";
2
3
  import { type ReactionBarItem } from "./ReactionBar";
3
4
  export type MessageRowAuthor = {
4
5
  /** Display name, shown at the start of a group and read before every message. */
@@ -11,12 +12,26 @@ export type MessageRowAuthor = {
11
12
  export type MessageRowStatus = "pending" | "sent" | "failed";
12
13
  export type MessageRowAction = {
13
14
  id: string;
14
- /** Accessible name and tooltip. */
15
+ /** Visible name of the menu entry. */
15
16
  label: string;
16
17
  /** Icon class, for example `ti ti-arrow-back-up`. */
17
18
  icon: string;
19
+ /** One quiet sentence below the label that says what the entry does. */
20
+ description?: string;
18
21
  onSelect: () => void;
19
22
  disabled?: boolean;
23
+ variant?: "danger";
24
+ /** A touch gesture that runs the entry too. Give each gesture to at most one entry. */
25
+ gesture?: GestureKind;
26
+ /**
27
+ * Alt+click (Option+click on Apple devices) on the message runs the entry directly, and the entry shows that
28
+ * shortcut. Give it to at most one entry.
29
+ */
30
+ altClick?: boolean;
31
+ /** A key the application handles for the focused message, such as "r"; the entry shows it at its end. */
32
+ shortcut?: string;
33
+ /** In the phone sheet, runs while the tap still counts as the person's gesture, as clipboard writes require. */
34
+ immediate?: boolean;
20
35
  };
21
36
  export type MessageRowQuote = {
22
37
  /** Name of the quoted message's author. */
@@ -67,6 +82,16 @@ export type MessageRowFile = MessageRowAttachmentTarget & {
67
82
  icon?: string;
68
83
  };
69
84
  export type MessageRowAttachment = MessageRowMedia | MessageRowFile;
85
+ /** Where a message belongs, shown as a small chip under it, for example its thread in a timeline of several. */
86
+ export type MessageRowOrigin = {
87
+ label: string;
88
+ /** Icon class, for example `ti ti-hash`. */
89
+ icon?: string;
90
+ /** Opens where the message belongs. Without it, the chip is not a control. */
91
+ onSelect?: () => void;
92
+ /** Accessible name of the control when it must say more than the label, such as "Open thread Updates". */
93
+ selectLabel?: string;
94
+ };
70
95
  export type MessageRowProgress = {
71
96
  /** What is happening, for example "Writing" or "Searching the files". */
72
97
  status: string;
@@ -96,7 +121,12 @@ export type MessageRowProps = {
96
121
  receipt?: string;
97
122
  /** Called by "Retry" while `status` is `"failed"`. */
98
123
  onRetry?: () => void;
99
- /** Shown as a toolbar over the message while it is hovered or focused. It never moves the layout. */
124
+ /** Called by "Discard" next to "Retry" while `status` is `"failed"`, so both answers to a failure sit where it shows. */
125
+ onDiscard?: () => void;
126
+ /**
127
+ * The message's menu. A quiet "…" beside the bubble opens it while the message is hovered or focused, also from the
128
+ * keyboard; right-click and a long press open the same menu. Showing "…" never moves the layout.
129
+ */
100
130
  actions?: readonly MessageRowAction[];
101
131
  /** The message this one answers, shown above it. */
102
132
  quote?: MessageRowQuote;
@@ -124,6 +154,8 @@ export type MessageRowProps = {
124
154
  onAddReaction?: (anchor: HTMLElement) => void;
125
155
  /** A bar of fixed height that opens the replies to this message. */
126
156
  thread?: MessageRowThread;
157
+ /** A chip of fixed height under the message that names where it belongs. */
158
+ origin?: MessageRowOrigin;
127
159
  /** The message is still being written, by a person or an automated author alike: a status line with "Stop". */
128
160
  progress?: MessageRowProgress;
129
161
  class?: string;
@@ -138,6 +170,29 @@ export type MessageSystemRowProps = {
138
170
  icon?: string;
139
171
  class?: string;
140
172
  };
173
+ export type MessageEventRowProps = {
174
+ /** What changed, for example "Mara set the status to “In review”". */
175
+ children: JSX.Element;
176
+ /** Icon class of the kind of change; a dot by default. */
177
+ icon?: string;
178
+ /** Where the change belongs, such as its thread, where several threads mix. */
179
+ origin?: MessageRowOrigin;
180
+ /** Visible time, formatted by the caller. */
181
+ time?: string;
182
+ dateTime?: string | Date;
183
+ class?: string;
184
+ };
185
+ export type MessageEventGroupProps = {
186
+ /** What the closed group stands for, for example "4 changes to Invitation and Light test". */
187
+ label: string;
188
+ expanded: boolean;
189
+ onToggle: () => void;
190
+ /** Visible time or range, formatted by the caller, for example "09:50–09:58". */
191
+ time?: string;
192
+ /** The first event's time. */
193
+ dateTime?: string | Date;
194
+ class?: string;
195
+ };
141
196
  export type MessageGroupEntry = {
142
197
  /** Stable identity of the author. */
143
198
  author: string;
@@ -156,6 +211,13 @@ export declare const startsMessageGroup: (entry: MessageGroupEntry, previous?: M
156
211
  * as `VirtualFeed` keeps its positions.
157
212
  */
158
213
  export declare function MessageRow(props: MessageRowProps): JSX.Element;
214
+ /**
215
+ * A quiet line for a change to something the conversation is about, such as a task's new status: no bubble, aligned
216
+ * with the messages' text, with its time at the end. It is no message: it never counts as unread.
217
+ */
218
+ export declare function MessageEventRow(props: MessageEventRowProps): JSX.Element;
219
+ /** Several event lines in a row as one line that opens them, such as "4 changes to Invitation and Light test". */
220
+ export declare function MessageEventGroup(props: MessageEventGroupProps): JSX.Element;
159
221
  /** A quiet, centered line for something that happened in the conversation, such as a person joining. */
160
222
  export declare function MessageSystemRow(props: MessageSystemRowProps): JSX.Element;
161
223
  export {};
@@ -6,9 +6,11 @@
6
6
  * in token spans, so the returned strings are safe to inject with
7
7
  * `innerHTML`.
8
8
  */
9
- export type CodeDisplayLanguage = "ts" | "tsx" | "js" | "jsx" | "script" | "markdown" | "md" | "text";
9
+ export type CodeDisplayLanguage = "ts" | "tsx" | "js" | "jsx" | "script" | "markdown" | "md" | "text" | "sql";
10
10
  export declare const escapeCodeHtml: (s: string) => string;
11
11
  export declare const highlightCode: (code: string) => string;
12
12
  export declare const highlightMarkdownDisplay: (code: string) => string;
13
13
  export declare const highlightCodeDisplayLines: (code: string, language?: CodeDisplayLanguage) => string[];
14
14
  export declare const highlightCodeDisplay: (code: string, language?: CodeDisplayLanguage) => string;
15
+ /** Display-only, tolerant of incomplete SQL while typing. Source is always escaped. */
16
+ export declare const highlightSql: (code: string) => string;
@@ -17,6 +17,7 @@ export type { ChartDatumRef, ChartSelection, ChartTooltip, ChartTooltipFormatter
17
17
  export type { ChartSnapshot } from "./chart-snapshot";
18
18
  export { prepareChartSnapshot } from "./chart-snapshot";
19
19
  export type { StateTimelineChartOptions, StateTimelineDomain, StateTimelineInterval, StateTimelineRow, StateTimelineState, } from "./chart-state-timeline";
20
+ export { highlightSql } from "./code-highlight";
20
21
  export { type CollectionSelection, createCollectionSelection, type SelectionModifiers } from "./collection-selection";
21
22
  export type { DataTableColumn, DataTableControlsProps, DataTableFooter, DataTableHeaderProps, DataTablePanelFooterProps, DataTablePanelProps, DataTableProps, DataTableRenderCell, DataTableRenderHeader, DataTableSort, } from "./DataTable";
22
23
  export { default as DataTable } from "./DataTable";
@@ -39,8 +40,8 @@ export { MapAttribution } from "./MapAttribution";
39
40
  export { MapView } from "./MapView";
40
41
  export { MapViewFrame } from "./MapViewFrame";
41
42
  export { default as MarkdownView, type MarkdownRenderOptions, type MarkdownViewProps, renderSafeMarkdown } from "./MarkdownView";
42
- export type { MessageGroupEntry, MessageRowAction, MessageRowAttachment, MessageRowAuthor, MessageRowFile, MessageRowMedia, MessageRowProgress, MessageRowProps, MessageRowQuote, MessageRowReaction, MessageRowStatus, MessageRowThread, MessageSystemRowProps, } from "./MessageRow";
43
- export { MessageRow, MessageSystemRow, startsMessageGroup } from "./MessageRow";
43
+ export type { MessageEventGroupProps, MessageEventRowProps, MessageGroupEntry, MessageRowAction, MessageRowAttachment, MessageRowAuthor, MessageRowFile, MessageRowMedia, MessageRowOrigin, MessageRowProgress, MessageRowProps, MessageRowQuote, MessageRowReaction, MessageRowStatus, MessageRowThread, MessageSystemRowProps, } from "./MessageRow";
44
+ export { MessageEventGroup, MessageEventRow, MessageRow, MessageSystemRow, startsMessageGroup } from "./MessageRow";
44
45
  export { type MapPaletteColors, type MapTheme, mapPalette } from "./map-palette";
45
46
  export { type MapStyleOptions, mapAttribution, mapStyle } from "./map-style";
46
47
  export type { MapViewArea, MapViewFit, MapViewFrameProps, MapViewLine, MapViewLineTone, MapViewMarker, MapViewOwnLocation, MapViewPoint, MapViewProps, MapViewStyle, MapViewStyleSource, MapViewTone, } from "./map-view-types";
@@ -1,2 +1,2 @@
1
1
  import { Map, type MapOptions } from "maplibre-gl";
2
- export declare function createMap(options: MapOptions): Map;
2
+ export declare function createMap(options: MapOptions, onResourceError: () => void): Map;
@@ -58,4 +58,6 @@ export type MapViewProps = Omit<MapViewFrameProps, "attribution"> & {
58
58
  notice?: JSX.Element;
59
59
  empty?: JSX.Element;
60
60
  onLocate?: () => void;
61
+ /** Observe rendering and resource failures without receiving provider responses or URLs. */
62
+ onStateChange?: (state: "static" | "loading" | "ready" | "error" | "no-webgl" | "empty") => void;
61
63
  };
@@ -8,6 +8,9 @@ export type OpenDialogOptions = {
8
8
  initialFocus?: "first-input" | "none" | ((dialog: HTMLDialogElement) => HTMLElement | null);
9
9
  cancelBehavior?: "resolve-undefined" | "ignore";
10
10
  ariaLabel?: string;
11
+ ariaDescribedBy?: string;
12
+ /** Use for a consequential confirmation that requires a response. Defaults to dialog. */
13
+ role?: "dialog" | "alertdialog";
11
14
  /**
12
15
  * Add a same-URL history entry while the dialog is open, so the browser's or the phone's Back closes the dialog
13
16
  * instead of leaving the page. Normally closing the dialog removes the entry again; the returned promise settles after that.
@@ -14,7 +14,12 @@ export type AutocompleteEditorProps = ValueFieldProps<string> & {
14
14
  name?: string;
15
15
  maxLength?: number;
16
16
  textareaRef?: (element: HTMLTextAreaElement) => void;
17
- variant?: "default" | "paper";
17
+ variant?: "default" | "paper" | "embedded";
18
+ readOnly?: boolean;
19
+ /** Number logical lines; disables soft wrapping to keep the gutter aligned. */
20
+ lineNumbers?: boolean;
21
+ /** One-based line to mark in the gutter, for example a parser error. */
22
+ markedLine?: number;
18
23
  };
19
24
  export declare function AutocompleteEditor(props: AutocompleteEditorProps): JSX.Element;
20
25
  export type { Completion, SuggestContext, Suggestion } from "./completion";
@@ -0,0 +1,93 @@
1
+ import { type JSX } from "solid-js";
2
+ import type { ValueFieldProps } from "./field-contract";
3
+ import type { ChoiceAppearance } from "./Select";
4
+ /** One option: a name plus at most one short line. */
5
+ export type RichSelectItem = {
6
+ value: string;
7
+ /** Wraps; never truncated. */
8
+ label: string;
9
+ /** At most one short line that says what the choice changes. */
10
+ description?: string;
11
+ /** Icon class shown before the name. */
12
+ icon?: string;
13
+ /** Color dot shown before the name, such as a space color. Replaces `icon`. */
14
+ color?: string;
15
+ /** Creates a fresh visual for each render location. Replaces `icon` and `color`. */
16
+ visual?: () => JSX.Element;
17
+ /** Makes the row unavailable. The reason replaces `description`; the arrow keys still reach the row. */
18
+ disabledReason?: string;
19
+ /** Section id. Headings show only from eight options; keep each section's items together. */
20
+ section?: string;
21
+ /** Extra search terms that are not shown. */
22
+ keywords?: readonly string[];
23
+ };
24
+ export type RichSelectSection = {
25
+ id: string;
26
+ label: string;
27
+ };
28
+ export type RichSelectStatus = "ready" | "loading" | "error";
29
+ export type RichSelectFooter = {
30
+ label: string;
31
+ icon?: string;
32
+ onActivate: () => void;
33
+ } | {
34
+ label: string;
35
+ icon?: string;
36
+ create: {
37
+ placeholder: string;
38
+ onCreate: (name: string) => void;
39
+ };
40
+ };
41
+ export type RichSelectFact = {
42
+ icon: string;
43
+ text: JSX.Element;
44
+ tone?: "default" | "warning";
45
+ };
46
+ export type RichSelectProps = ValueFieldProps<string | null> & {
47
+ items: readonly RichSelectItem[];
48
+ /** Labels for the `section` ids of the items. */
49
+ sections?: readonly RichSelectSection[];
50
+ /** Names the list: the heading of a list without preview, the phone sheet title, and the listbox label. */
51
+ title?: string;
52
+ placeholder?: string;
53
+ /** Replaces the selected item's name in the trigger, such as "Name · address". */
54
+ triggerLabel?: string;
55
+ /** Icon class for the trigger while no item with its own visual is selected. */
56
+ icon?: string;
57
+ tone?: "default" | "warning";
58
+ /** Custom content inside the shared trigger button, which keeps the combobox semantics. */
59
+ renderTrigger?: (selected: RichSelectItem | undefined) => JSX.Element;
60
+ /**
61
+ * The body of the preview beside the list, for options whose consequences differ.
62
+ * Without it the picker shows only the list. Keep it to at most three facts.
63
+ */
64
+ renderPreview?: (item: RichSelectItem) => JSX.Element;
65
+ searchPlaceholder?: string;
66
+ status?: RichSelectStatus;
67
+ onRetry?: () => void;
68
+ /** Shown when the list is ready and has no items. */
69
+ empty?: JSX.Element;
70
+ footer?: RichSelectFooter;
71
+ appearance?: ChoiceAppearance;
72
+ placement?: "bottom-start" | "top-start";
73
+ /** CSS lengths for the desktop popover. */
74
+ size?: {
75
+ width?: string;
76
+ height?: string;
77
+ };
78
+ name?: string;
79
+ };
80
+ /** Search and section headings appear from this many options. */
81
+ export declare const RICH_SELECT_SEARCH_FROM = 8;
82
+ /** Up to three short facts for a preview, each with an icon; warnings in the warning tone. */
83
+ export declare function RichSelectFacts(props: {
84
+ facts: readonly RichSelectFact[];
85
+ }): JSX.Element;
86
+ /**
87
+ * A dropdown whose rows explain each choice: a name plus one short line, an
88
+ * unavailable row with its reason, and an optional preview of what a choice
89
+ * changes. Desktop opens a popover beside the trigger; a phone opens a bottom
90
+ * sheet whose info buttons show the preview as a second level.
91
+ */
92
+ export declare function RichSelect(props: RichSelectProps): JSX.Element;
93
+ export default RichSelect;
@@ -5,9 +5,12 @@ export type TextInputProps = Omit<JSX.InputHTMLAttributes<HTMLInputElement>, "on
5
5
  minLength?: number;
6
6
  maxLength?: number;
7
7
  type?: "text" | "search" | "email" | "url" | "tel";
8
- variant?: "default" | "ai";
9
- icon?: string;
8
+ variant?: "default" | "ai" | "compact";
9
+ /** Set false for a plain field without a leading icon. */
10
+ icon?: string | false;
10
11
  activeIcon?: string;
12
+ /** ID of a consumer-owned visible error; caller owns its announcement. Native controls only. */
13
+ externalErrorId?: string;
11
14
  prefix?: JSX.Element;
12
15
  suffix?: JSX.Element;
13
16
  clearable?: boolean;
@@ -10,8 +10,19 @@ export type ChoiceOption<T extends string = string> = {
10
10
  groups?: readonly string[];
11
11
  };
12
12
  export type ChoiceOptionsLoader<T extends string = string> = (query: string, signal: AbortSignal) => Promise<readonly ChoiceOption<T>[]>;
13
- export declare const filterChoiceOptions: <T extends string>(options: readonly ChoiceOption<T>[], query: string) => readonly ChoiceOption<T>[];
14
- export declare const nextEnabledChoiceIndex: <T extends string>(options: readonly ChoiceOption<T>[], current: number, direction: 1 | -1) => number;
13
+ /** Matches label, description, value, and optional extra keywords. */
14
+ export declare const filterChoiceOptions: <O extends Pick<ChoiceOption<string>, "label" | "description" | "value"> & {
15
+ keywords?: readonly string[];
16
+ }>(options: readonly O[], query: string) => readonly O[];
17
+ /**
18
+ * Moves through the options and wraps at the ends, skipping `disabled` ones. A
19
+ * RichSelect row that cannot be chosen carries a `disabledReason` instead, so
20
+ * the arrow keys still reach it and its reason can be read.
21
+ */
22
+ export declare const nextEnabledChoiceIndex: <O extends {
23
+ label: string;
24
+ disabled?: boolean;
25
+ }>(options: readonly O[], current: number, direction: 1 | -1) => number;
15
26
  /**
16
27
  * Counts the leading pills that fit into `available` pixels and measures the
17
28
  * whole row. When not all of them fit, the rest collapse into a summary pill
@@ -32,8 +43,17 @@ export declare function createChoiceLoader<T extends string>(loader: () => Choic
32
43
  retry: () => void;
33
44
  cancel: () => void;
34
45
  };
35
- export declare const placeChoicePopover: (trigger: HTMLElement, popover: HTMLElement) => void;
36
- export declare function createChoicePopover(disabled: () => boolean): {
46
+ export type ChoicePopoverPlacement = {
47
+ /**
48
+ * `trigger` (default) gives the popover the trigger's width; `own` keeps the
49
+ * width its stylesheet sets, such as a RichSelect with a preview.
50
+ */
51
+ width?: "trigger" | "own";
52
+ /** The side tried first. The popover flips when the other side has more room. */
53
+ side?: "below" | "above";
54
+ };
55
+ export declare const placeChoicePopover: (trigger: HTMLElement, popover: HTMLElement, placement?: ChoicePopoverPlacement) => void;
56
+ export declare function createChoicePopover(disabled: () => boolean, placement?: () => ChoicePopoverPlacement): {
37
57
  open: () => boolean;
38
58
  setTrigger: Setter<HTMLElement | undefined>;
39
59
  setPopover: Setter<HTMLElement | undefined>;
@@ -37,6 +37,8 @@ export type { NumberInputProps } from "./NumberInput";
37
37
  export { NumberInput } from "./NumberInput";
38
38
  export type { QrScannerError, QrScannerProps } from "./QrScanner";
39
39
  export { QrScanner } from "./QrScanner";
40
+ export type { RichSelectFact, RichSelectFooter, RichSelectItem, RichSelectProps, RichSelectSection, RichSelectStatus, } from "./RichSelect";
41
+ export { RichSelect, RichSelectFacts } from "./RichSelect";
40
42
  export type { ChoiceAppearance, SelectGridSize, SelectGroup, SelectOption, SelectProps, SelectSourceOption, SelectView } from "./Select";
41
43
  export { Select } from "./Select";
42
44
  export type { SelectChipOption, SelectChipProps } from "./SelectChip";
@@ -0,0 +1,21 @@
1
+ declare const richSelectMessages: import("@k2b/stdlib").Catalog<{
2
+ back: string;
3
+ choose: string;
4
+ chooseOption: string;
5
+ close: string;
6
+ couldNotLoad: string;
7
+ create: string;
8
+ detailsFor: ({ name }: {
9
+ name: string;
10
+ }) => string;
11
+ loading: string;
12
+ noOptions: string;
13
+ noResults: string;
14
+ retry: string;
15
+ search: string;
16
+ }>;
17
+ export type RichSelectMessages = ReturnType<(typeof richSelectMessages)["resolve"]>["t"];
18
+ /** Resolved from the inherited render locale. */
19
+ export declare const useRichSelectMessages: () => (() => RichSelectMessages);
20
+ export declare const checkRichSelectMessages: () => import("@k2b/stdlib").CatalogIssue[];
21
+ export {};
@@ -26,6 +26,8 @@ export declare const resolveShortcutMessages: (locale?: string) => {
26
26
  pageup: string;
27
27
  pagedown: string;
28
28
  spaceLabel: string;
29
+ click: string;
30
+ clickLabel: string;
29
31
  deleteLabel: string;
30
32
  homeLabel: string;
31
33
  endLabel: string;
@@ -6,6 +6,8 @@ import type { ScrollAreaProps } from "./ScrollArea";
6
6
  import { type AppWorkspaceSidebarSwitcherProps } from "./SidebarSwitcher";
7
7
  export type { AppWorkspaceWidthShare } from "./app-workspace-width";
8
8
  export type AppWorkspaceHeadProps = {
9
+ /** Below 48rem, show this head only with this active Main region. Unsplit Mains keep their head. */
10
+ mobilePane?: string;
9
11
  /** View tabs, usually a ViewTabs. */
10
12
  views?: JSX.Element;
11
13
  /** Filter chips, usually FilterChip elements. */
@@ -89,6 +91,8 @@ export type AppWorkspaceMainPaneProps = {
89
91
  href?: string;
90
92
  /** Quiet one-line text below the level title. */
91
93
  description?: JSX.Element;
94
+ /** Levels mode: a small mark before the level title, such as the colour dot of the object's container. */
95
+ lead?: JSX.Element;
92
96
  /** Controls at the end of the level head. */
93
97
  actions?: JSX.Element;
94
98
  surface?: "default" | "navigation";
@@ -107,6 +111,10 @@ export type AppWorkspaceDetailWidth = "sm" | "md" | "lg" | "xl";
107
111
  export type AppWorkspaceDetailProps = {
108
112
  children: JSX.Element;
109
113
  open: boolean;
114
+ /** Keeps the shared head control reachable while closed; set the app's existing open state synchronously. */
115
+ onOpen?: () => void;
116
+ /** Whether the current object may show details. False disables reopening and hides the panel. */
117
+ available?: boolean;
110
118
  /**
111
119
  * Whether choosing an item in Main opens this Detail as the drawer while it waits.
112
120
  * Set false when Main itself shows the chosen item, such as a reader beside a list:
@@ -124,6 +132,7 @@ export type AppWorkspaceDetailProps = {
124
132
  maxWidth?: number;
125
133
  /**
126
134
  * Closes the column with Escape, or the phone sheet with a downward drag.
135
+ * With onOpen, the shared head control also closes the column or phone sheet.
127
136
  * Server-rendered panels mark their close control with
128
137
  * `data-workspace-detail-close` instead; those gestures click it.
129
138
  * Escape and a rightward touch swipe park an open waiting drawer without
@@ -2,6 +2,8 @@ import { type JSX } from "solid-js";
2
2
  import { type ButtonLinkProps, type ButtonProps } from "../actions/Button";
3
3
  import { type DropdownItem } from "../actions/Dropdown";
4
4
  export type DetailPanelProps = {
5
+ /** Plain sections share their host surface, as in AppWorkspace.Detail. */
6
+ surface?: "default" | "plain";
5
7
  children: JSX.Element;
6
8
  class?: string;
7
9
  };