@knitify/vue 1.0.0 → 2.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 (97) hide show
  1. package/README.md +113 -86
  2. package/dist/index.es.js +5773 -1451
  3. package/dist/index.umd.js +1 -1
  4. package/dist/types/components/Alert/KAlert.vue.d.ts +22 -2
  5. package/dist/types/components/Alert/types.d.ts +11 -1
  6. package/dist/types/components/ArticleList/KArticleList.vue.d.ts +11 -0
  7. package/dist/types/components/ArticleList/KArticleListItem.vue.d.ts +15 -0
  8. package/dist/types/components/ArticleList/types.d.ts +40 -0
  9. package/dist/types/components/Avatar/KAvatar.vue.d.ts +5 -1
  10. package/dist/types/components/Avatar/types.d.ts +92 -4
  11. package/dist/types/components/Badge/types.d.ts +2 -0
  12. package/dist/types/components/Calendar/types.d.ts +2 -0
  13. package/dist/types/components/Chat/KChatDivider.vue.d.ts +11 -0
  14. package/dist/types/components/Chat/KChatMessageActions.vue.d.ts +18 -0
  15. package/dist/types/components/Chat/KChatNotice.vue.d.ts +11 -0
  16. package/dist/types/components/Chat/KChatPrompt.vue.d.ts +1 -1
  17. package/dist/types/components/Chat/keys.d.ts +1 -0
  18. package/dist/types/components/Chat/types.d.ts +109 -4
  19. package/dist/types/components/ChatDock/KChatDock.vue.d.ts +47 -0
  20. package/dist/types/components/ChatDock/KChatDockItem.vue.d.ts +11 -0
  21. package/dist/types/components/ChatDock/KChatDockPanel.vue.d.ts +11 -0
  22. package/dist/types/components/ChatDock/KChatNewWindow.vue.d.ts +28 -0
  23. package/dist/types/components/ChatDock/KChatWindow.vue.d.ts +27 -0
  24. package/dist/types/components/ChatDock/KMessenger.vue.d.ts +29 -0
  25. package/dist/types/components/ChatDock/keys.d.ts +98 -0
  26. package/dist/types/components/ChatDock/messenger-types.d.ts +335 -0
  27. package/dist/types/components/ChatDock/store-keys.d.ts +7 -0
  28. package/dist/types/components/ChatDock/types.d.ts +162 -0
  29. package/dist/types/components/ChatDock/useChatDock.d.ts +11 -0
  30. package/dist/types/components/Collapse/KCollapse.vue.d.ts +2 -2
  31. package/dist/types/components/Collapse/useCollapseSync.d.ts +7 -5
  32. package/dist/types/components/DateInput/KDateInput.vue.d.ts +26 -0
  33. package/dist/types/components/DateInput/KDateRangeInput.vue.d.ts +31 -0
  34. package/dist/types/components/DateInput/types.d.ts +69 -0
  35. package/dist/types/components/DateInput/useDateInput.d.ts +27 -0
  36. package/dist/types/components/Divider/KDivider.vue.d.ts +11 -0
  37. package/dist/types/components/Divider/types.d.ts +19 -0
  38. package/dist/types/components/Drawer/KDrawer.vue.d.ts +3 -3
  39. package/dist/types/components/Dropdown/KDropdown.vue.d.ts +2 -2
  40. package/dist/types/components/Field/FieldIsolate.d.ts +4 -0
  41. package/dist/types/components/Field/KField.vue.d.ts +11 -0
  42. package/dist/types/components/Field/keys.d.ts +21 -0
  43. package/dist/types/components/Field/types.d.ts +35 -0
  44. package/dist/types/components/Flex/KFlex.vue.d.ts +11 -0
  45. package/dist/types/components/Flex/types.d.ts +26 -0
  46. package/dist/types/components/Input/KInput.vue.d.ts +2 -0
  47. package/dist/types/components/Input/types.d.ts +11 -1
  48. package/dist/types/components/Modal/KModal.vue.d.ts +3 -3
  49. package/dist/types/components/Modal/types.d.ts +5 -1
  50. package/dist/types/components/Pagination/KPagination.vue.d.ts +13 -0
  51. package/dist/types/components/Pagination/range.d.ts +6 -0
  52. package/dist/types/components/Pagination/types.d.ts +20 -0
  53. package/dist/types/components/Popover/KPopover.vue.d.ts +2 -2
  54. package/dist/types/components/Popover/useOverlaySync.d.ts +15 -1
  55. package/dist/types/components/RadioCard/KRadioCard.vue.d.ts +20 -0
  56. package/dist/types/components/RadioCard/KRadioCardGroup.vue.d.ts +11 -0
  57. package/dist/types/components/RadioCard/types.d.ts +25 -0
  58. package/dist/types/components/SearchInput/KSearchInput.vue.d.ts +22 -0
  59. package/dist/types/components/SearchInput/types.d.ts +7 -0
  60. package/dist/types/components/SegmentedButtons/KSegmentedButton.vue.d.ts +20 -0
  61. package/dist/types/components/SegmentedButtons/KSegmentedButtons.vue.d.ts +11 -0
  62. package/dist/types/components/SegmentedButtons/types.d.ts +25 -0
  63. package/dist/types/components/Select/KSelect.vue.d.ts +2 -0
  64. package/dist/types/components/Select/types.d.ts +8 -0
  65. package/dist/types/components/Skeleton/KSkeleton.vue.d.ts +4 -0
  66. package/dist/types/components/Skeleton/types.d.ts +19 -0
  67. package/dist/types/components/Spinner/KSpinner.vue.d.ts +6 -0
  68. package/dist/types/components/Spinner/types.d.ts +13 -0
  69. package/dist/types/components/Table/KTable.vue.d.ts +8 -1
  70. package/dist/types/components/Table/KTableResizer.vue.d.ts +4 -0
  71. package/dist/types/components/Table/types.d.ts +27 -2
  72. package/dist/types/components/Tabs/types.d.ts +25 -3
  73. package/dist/types/components/TagsInput/KTagsInput.vue.d.ts +32 -0
  74. package/dist/types/components/TagsInput/types.d.ts +68 -0
  75. package/dist/types/components/TagsInput/useTagsInput.d.ts +27 -0
  76. package/dist/types/components/Time/KTime.vue.d.ts +18 -0
  77. package/dist/types/components/Time/types.d.ts +23 -0
  78. package/dist/types/components/TimeInput/KTimeInput.vue.d.ts +26 -0
  79. package/dist/types/components/TimeInput/types.d.ts +27 -0
  80. package/dist/types/components/TimeInput/useTimeInput.d.ts +22 -0
  81. package/dist/types/components/Toggle/types.d.ts +2 -0
  82. package/dist/types/components/Tooltip/triggerHandlers.d.ts +33 -0
  83. package/dist/types/components/Tooltip/types.d.ts +5 -0
  84. package/dist/types/components/Tooltip/vTooltip.d.ts +10 -0
  85. package/dist/types/components/Workspace/KWorkspace.vue.d.ts +13 -1
  86. package/dist/types/components/Workspace/types.d.ts +10 -0
  87. package/dist/types/components/index.d.ts +34 -0
  88. package/dist/types/components/types.d.ts +19 -0
  89. package/dist/types/index.d.ts +1 -0
  90. package/dist/types/utils/useCoreModule.d.ts +30 -0
  91. package/dist/types/utils/useDocumentEvent.d.ts +19 -0
  92. package/dist/types/utils/useExclusive.d.ts +13 -0
  93. package/dist/types/utils/useFieldControl.d.ts +25 -0
  94. package/dist/types/utils/useRootClasses.d.ts +15 -0
  95. package/dist/types/utils/useTopmost.d.ts +17 -0
  96. package/dist/web-types.json +7986 -0
  97. package/package.json +17 -5
@@ -0,0 +1,98 @@
1
+ import type { InjectionKey, ShallowRef } from 'vue';
2
+ import type Knitify from '@knitify/core';
3
+ export type ChatDockInstance = InstanceType<typeof Knitify.modules.ChatDock>;
4
+ /**
5
+ * What `withModule` did, so a caller can react to each outcome distinctly:
6
+ *
7
+ * - `'called'` — the callback ran against a live module. Anything the caller
8
+ * wanted to tell core has been told.
9
+ * - `'deferred'` — a dock is present but its first `init()` has not run yet,
10
+ * so nothing may reach core (see `withModule`). The callback did **not**
11
+ * run; the caller must record its intent through `declare` instead, and the
12
+ * dock replays it the moment calling core becomes safe.
13
+ * - `'unavailable'` — there is no module to call at all: no `KChatDock`
14
+ * ancestor, or the dock's own root is gone. The callback did **not** run and
15
+ * nothing was or will be recorded, so a caller must not update bookkeeping
16
+ * that claims core was told something.
17
+ */
18
+ export type ChatDockCallResult = 'called' | 'deferred' | 'unavailable';
19
+ export type ChatDockContext = {
20
+ /**
21
+ * **The only way to reach core from anywhere in this component pair.** The
22
+ * module instance is deliberately not exposed: a call site that cannot get
23
+ * hold of it cannot skip the gate below by accident, which is what four
24
+ * successive rounds of path-specific patching kept failing to prevent.
25
+ *
26
+ * The gate: no core call may happen before the dock's own first deferred
27
+ * `init()` has run. Every core method reflows synchronously before it
28
+ * returns, and a reflow dispatches `kt.chatdock.rail`/`.unrail` to whichever
29
+ * windows changed — but a child window attaches those listeners from a
30
+ * template-ref watcher, which lands a flush *after* its parent's
31
+ * `onMounted`, and Vue orders pre-flush jobs by component creation order, so
32
+ * the dock's own watchers and an earlier sibling's watchers all run while a
33
+ * later sibling is still deaf. An event dropped that way is lost for good:
34
+ * Vue never re-patches a `class` binding whose rendered string is unchanged,
35
+ * so core's directly-set `is-railed` survives on the element while
36
+ * `v-model:state` (and `aria-expanded`) stay wrong forever, and every later
37
+ * reflow is a no-op diff that never repairs it.
38
+ *
39
+ * Skipping a pre-init call costs nothing, which is what makes the gate safe
40
+ * rather than merely cautious: the deferred `init()` applies every pending
41
+ * declaration and reflows anyway, so it subsumes whatever was skipped.
42
+ *
43
+ * Also flushes any pending declarations through core immediately before
44
+ * running the callback, so a `reflow()` never computes capacity against a
45
+ * window core has not yet been told is railed.
46
+ */
47
+ withModule: (run: (module: ChatDockInstance) => void) => ChatDockCallResult;
48
+ /**
49
+ * Records whether a window should be railed once the dock next applies its
50
+ * declarations — no class, no attribute, no method call yet. `KChatDock`
51
+ * plays every recorded declaration through core itself, from its deferred
52
+ * first `init()` and again before every later core call (see `withModule`),
53
+ * which are the only points every window is guaranteed to have already
54
+ * attached its own `kt.chatdock.*` listeners.
55
+ *
56
+ * This is where state intent goes whenever `withModule` reports
57
+ * `'deferred'`, and where a window's own initial non-expanded state goes at
58
+ * mount.
59
+ *
60
+ * With only two states left, this only ever records `railed` — an
61
+ * `'expanded'` window needs nothing (that's what a freshly-seeded window
62
+ * already is), and `railed` needs a core call because only core's `rail()`
63
+ * sets the `data-kt-chat-window-minimized` marker `reflow()` reads to tell
64
+ * an explicit minimize apart from a window merely ranked below capacity.
65
+ *
66
+ * Idempotent both ways: declaring the same element `railed` repeatedly, or
67
+ * un-declaring it (passing `false`) before it's ever applied, just leaves
68
+ * one net entry (or none) — whichever a window's most recent write before
69
+ * the dock's next apply says is true.
70
+ */
71
+ declare: (element: HTMLElement, railed: boolean) => void;
72
+ /**
73
+ * The rail element, as a ref, so a window can teleport its head into it.
74
+ *
75
+ * A ref rather than the element itself because the rail is rendered by the
76
+ * dock and a window may set up before it resolves; `<Teleport defer>`
77
+ * handles a target that appears later in the same tree, and the ref is what
78
+ * lets the window react when it does.
79
+ *
80
+ * This is not a way around the gate: teleporting renders markup, it does
81
+ * not call core. Every core call still goes through `withModule`.
82
+ */
83
+ rail: Readonly<ShallowRef<HTMLElement | null>>;
84
+ /**
85
+ * The popover list element, as a ref, so a window can teleport its row into
86
+ * it. Same shape and reasoning as `rail`: the dock renders it, a window may
87
+ * set up before it resolves, and `<Teleport defer>` handles a target that
88
+ * appears later in the same tree.
89
+ */
90
+ list: Readonly<ShallowRef<HTMLElement | null>>;
91
+ /**
92
+ * The row zone element, as a ref, so `KChatDockPanel` can teleport into it.
93
+ * Same shape and reasoning as `rail` and `list`. The panel's `order: -1`
94
+ * places it beside the rail regardless of where the teleport appends it.
95
+ */
96
+ panel: Readonly<ShallowRef<HTMLElement | null>>;
97
+ };
98
+ export declare const chatDockKey: InjectionKey<ChatDockContext>;
@@ -0,0 +1,335 @@
1
+ import type { ComputedRef, Ref } from 'vue';
2
+ export type ChatConversation = {
3
+ id: string;
4
+ name: string;
5
+ /** Image URL; the avatar falls back to initials from `name`. */
6
+ avatar?: string;
7
+ /** Last message line, shown in the panel row. */
8
+ preview?: string;
9
+ unread?: number;
10
+ /** ISO timestamp; when present the panel sorts newest first. */
11
+ updatedAt?: string;
12
+ /**
13
+ * Untouched by the store — carry app-specific payload through to the slots.
14
+ * Replaced, not merged, when `refreshConversations` returns a conversation
15
+ * that carries one: the merge is a shallow spread.
16
+ */
17
+ meta?: unknown;
18
+ };
19
+ export type ChatMessage = {
20
+ id: string;
21
+ conversationId: string;
22
+ text: string;
23
+ /** `true` for the current user; drives `KChatMessage`'s `sender`. */
24
+ sender: boolean;
25
+ /** Display string, e.g. "10:42 AM". */
26
+ time?: string;
27
+ /** ISO timestamp, for ordering by the server. */
28
+ sentAt?: string;
29
+ /** Optimistic send in flight; cleared when `sendMessage` resolves. */
30
+ pending?: boolean;
31
+ /** `sendMessage` rejected; the message shows a retry control. */
32
+ failed?: boolean;
33
+ /**
34
+ * Untouched by the store — carry app-specific payload through to the slots.
35
+ * An optimistic message created by `send()` has none; the message returned
36
+ * by `sendMessage` replaces it wholesale, so `meta` appears when the server
37
+ * response does.
38
+ */
39
+ meta?: unknown;
40
+ };
41
+ export type ChatMessagesPage = {
42
+ messages: ChatMessage[];
43
+ /** `null` or `undefined` means there is nothing older. */
44
+ nextCursor?: string | null;
45
+ };
46
+ export type ChatDockLoaders = {
47
+ loadConversations: () => Promise<ChatConversation[]>;
48
+ /** Chronological within the page (oldest first). `cursor` asks for older. */
49
+ loadMessages: (id: string, cursor?: string) => Promise<ChatMessagesPage>;
50
+ /** Optional; without it the composer is hidden. */
51
+ sendMessage?: (id: string, text: string) => Promise<ChatMessage>;
52
+ /** Optional; called when a window expands. Unread is zeroed locally either way. */
53
+ markRead?: (id: string) => Promise<void>;
54
+ };
55
+ export type ChatDockOptions = {
56
+ /** Drop messages, cursor and draft when a window closes. Default `false`. */
57
+ evictOnClose?: boolean;
58
+ /**
59
+ * Skip the list load the store otherwise starts on creation; nothing is
60
+ * fetched until `ensureConversations` (or `refreshConversations`) is
61
+ * called. `KMessenger` calls it when the panel first opens. Default `false`.
62
+ */
63
+ lazy?: boolean;
64
+ };
65
+ export type ChatWindowState = 'closed' | 'expanded' | 'railed';
66
+ export type LoadState = 'idle' | 'loading' | 'loaded' | 'error';
67
+ export type ChatEntry = {
68
+ conversation: ChatConversation;
69
+ window: ChatWindowState;
70
+ messages: ChatMessage[];
71
+ /** `undefined` until the first page loads; `null` when nothing older exists. */
72
+ cursor: string | null | undefined;
73
+ loading: LoadState;
74
+ loadingOlder: boolean;
75
+ error?: unknown;
76
+ draft: string;
77
+ };
78
+ export type ChatDockErrorKind = 'conversations' | 'messages' | 'send';
79
+ export type ChatDockStore = {
80
+ /** Sorted newest first when `updatedAt` is present on every entry. */
81
+ conversations: ComputedRef<ChatConversation[]>;
82
+ entries: Record<string, ChatEntry>;
83
+ /** Ids whose window is not `'closed'`, most recently opened first. */
84
+ openIds: ComputedRef<string[]>;
85
+ listLoading: Ref<LoadState>;
86
+ listError: Ref<unknown>;
87
+ query: Ref<string>;
88
+ /** Whether a composer can be rendered at all. */
89
+ canSend: boolean;
90
+ refreshConversations: () => Promise<void>;
91
+ /**
92
+ * Loads the list only if it has not loaded yet: starts a load when idle or
93
+ * failed, joins the one in flight, and does nothing once loaded. Safe to
94
+ * call on every panel open.
95
+ */
96
+ ensureConversations: () => Promise<void>;
97
+ open: (id: string) => Promise<void>;
98
+ /**
99
+ * Shows a window again without treating it as a user-initiated open: no
100
+ * rank change, no unread reset, no `markRead`, no `'open'` event. For a
101
+ * reflow un-railing a window; use `open` for a real choice.
102
+ */
103
+ expand: (id: string) => Promise<void>;
104
+ minimize: (id: string) => void;
105
+ close: (id: string) => void;
106
+ loadOlder: (id: string) => Promise<void>;
107
+ send: (id: string, text: string) => Promise<void>;
108
+ retry: (id: string, messageId: string) => Promise<void>;
109
+ retryLoad: (id: string) => Promise<void>;
110
+ receive: (message: ChatMessage) => void;
111
+ setDraft: (id: string, text: string) => void;
112
+ setQuery: (text: string) => void;
113
+ /**
114
+ * Fires after an action outcome, so a component can mirror it as an emit.
115
+ * Returns an unsubscribe function.
116
+ */
117
+ onEvent: (listener: (event: ChatDockEvent) => void) => () => void;
118
+ };
119
+ export type ChatDockEvent = {
120
+ type: 'open';
121
+ id: string;
122
+ } | {
123
+ type: 'close';
124
+ id: string;
125
+ } | {
126
+ type: 'send';
127
+ message: ChatMessage;
128
+ } | {
129
+ type: 'receive';
130
+ message: ChatMessage;
131
+ } | {
132
+ type: 'error';
133
+ kind: ChatDockErrorKind;
134
+ id?: string;
135
+ error: unknown;
136
+ };
137
+ export type KMessengerProps = {
138
+ /** The component creates its own store. Exactly one of `loaders` or `store`. */
139
+ loaders?: ChatDockLoaders;
140
+ /** A store created with `useChatDock` elsewhere and shared. */
141
+ store?: ChatDockStore;
142
+ minWindows?: number;
143
+ title?: string;
144
+ placeholder?: string;
145
+ /** The "New chat" window's title. Default `'New Chat'`. */
146
+ newChatTitle?: string;
147
+ /** The "New chat" people search placeholder. Default `'To: Search People'`. */
148
+ newChatPlaceholder?: string;
149
+ /** The "New chat" people search's accessible name. Default `'Search people'`. */
150
+ newChatSearchLabel?: string;
151
+ /** Passed to `useChatDock` when the component creates the store. */
152
+ evictOnClose?: boolean;
153
+ /**
154
+ * Passed to `useChatDock` when the component creates the store: the list
155
+ * loads when the panel first opens instead of on mount. Default `false`.
156
+ */
157
+ lazy?: boolean;
158
+ /**
159
+ * Passed to every window's `KChat`: stacks message actions under the bubble.
160
+ * Defaults to `true` — a dock window is too narrow to spare the width beside
161
+ * each bubble. Pass `false` to put them back at the side.
162
+ */
163
+ actionsBottom?: boolean;
164
+ /**
165
+ * Called for each message with the one before it. Return a label to render
166
+ * a divider above that message, or `undefined` for none. `previous` is
167
+ * `undefined` for the first message in the list.
168
+ *
169
+ * A boundary hook, not a date hook: an app tracking its own unread boundary
170
+ * returns "Unread messages" there and a day label elsewhere.
171
+ *
172
+ * Called for every message on every render, so compare pre-computed day
173
+ * keys here rather than parsing and formatting inside the callback.
174
+ */
175
+ dateLabel?: (message: ChatMessage, previous?: ChatMessage) => string | undefined;
176
+ /**
177
+ * Return a label to render this message as a `KChatNotice` instead of a
178
+ * `KChatMessage`. `undefined` renders it as a normal bubble.
179
+ *
180
+ * For an event that arrives in the same message stream as ordinary
181
+ * messages and is distinguished per message — "You left the meeting room",
182
+ * "Call ended at 01:48 PM".
183
+ *
184
+ * A notice renders no bubble, no sender side, no time and no actions row,
185
+ * and so no retry control either: a message carrying both `failed` and a
186
+ * notice label loses the way to retry it. Return `undefined` for a message
187
+ * still in flight. `dateLabel` still applies above a notice, so a day
188
+ * divider can precede one.
189
+ *
190
+ * Called for every message on every render, like `dateLabel` — read a
191
+ * pre-computed field here rather than deriving one inside the callback.
192
+ */
193
+ noticeLabel?: (message: ChatMessage) => string | undefined;
194
+ };
195
+ export type KMessengerEmits = {
196
+ open: [id: string];
197
+ close: [id: string];
198
+ send: [message: ChatMessage];
199
+ receive: [message: ChatMessage];
200
+ error: [kind: ChatDockErrorKind, id: string | undefined, error: unknown];
201
+ /** The panel's write button was clicked; the "New chat" window is open. */
202
+ compose: [];
203
+ /** Each keystroke in the "New chat" window's people search. */
204
+ 'new-chat-search': [query: string];
205
+ /** The "New chat" window was closed. */
206
+ 'new-chat-close': [];
207
+ };
208
+ export type KMessengerSlots = {
209
+ /** Inside the avatar circle of a head and a panel row. */
210
+ avatar?(props: {
211
+ conversation: ChatConversation;
212
+ }): any;
213
+ /**
214
+ * The window header's action area, before the minimize and close controls.
215
+ * `window-` prefixed because an unprefixed `title` would read as the dock's
216
+ * own title, which is already a prop, and `actions` would collide with the
217
+ * panel's.
218
+ */
219
+ 'window-actions'?(props: {
220
+ conversation: ChatConversation;
221
+ entry: ChatEntry;
222
+ }): any;
223
+ /** The window header's title text. */
224
+ 'window-title'?(props: {
225
+ conversation: ChatConversation;
226
+ entry: ChatEntry;
227
+ }): any;
228
+ /** Inside a railed head's avatar circle. Falls back to `avatar`. */
229
+ head?(props: {
230
+ conversation: ChatConversation;
231
+ entry: ChatEntry;
232
+ }): any;
233
+ /** Inside a `+N` popover row's avatar. Falls back to `avatar`. */
234
+ row?(props: {
235
+ conversation: ChatConversation;
236
+ entry: ChatEntry;
237
+ }): any;
238
+ /** The panel header's action area, before the write, maximize and close. */
239
+ 'panel-actions'?(): any;
240
+ /**
241
+ * The "New chat" window's body, under its people search — e.g. a "Create
242
+ * New Group" link and suggested people. `close` dismisses the window, for
243
+ * once a person is picked.
244
+ */
245
+ 'new-chat'?(props: {
246
+ close: () => void;
247
+ }): any;
248
+ /** The whole panel row. */
249
+ item?(props: {
250
+ conversation: ChatConversation;
251
+ entry: ChatEntry;
252
+ }): any;
253
+ /** One message bubble's content. */
254
+ message?(props: {
255
+ message: ChatMessage;
256
+ conversation: ChatConversation;
257
+ }): any;
258
+ /**
259
+ * The hover row beside a message's bubble — put a `KChatMessageActions`
260
+ * here. `message-` prefixed to match `window-actions` and `panel-actions`,
261
+ * which are the two headers rather than a message.
262
+ *
263
+ * Forwarded only when you pass it, so `KChatMessage`'s own empty actions
264
+ * rendering is unchanged otherwise. Not rendered for a message that
265
+ * `noticeLabel` turned into a notice.
266
+ */
267
+ 'message-actions'?(props: {
268
+ message: ChatMessage;
269
+ conversation: ChatConversation;
270
+ }): any;
271
+ /** The window footer. */
272
+ composer?(props: {
273
+ conversation: ChatConversation;
274
+ draft: string;
275
+ send: (text: string) => void;
276
+ setDraft: (text: string) => void;
277
+ }): any;
278
+ /**
279
+ * Extra controls on the default composer, scoped by conversation so one
280
+ * template serves every window: `prefix`/`suffix` inside the field border,
281
+ * `start`/`end` outside it (`end` sits before the send button). Ignored
282
+ * when `composer` replaces the whole footer.
283
+ */
284
+ 'composer-prefix'?(props: {
285
+ conversation: ChatConversation;
286
+ }): any;
287
+ 'composer-suffix'?(props: {
288
+ conversation: ChatConversation;
289
+ }): any;
290
+ 'composer-start'?(props: {
291
+ conversation: ChatConversation;
292
+ }): any;
293
+ 'composer-end'?(props: {
294
+ conversation: ChatConversation;
295
+ }): any;
296
+ /** Window body while the first page loads. */
297
+ loading?(props: {
298
+ conversation: ChatConversation;
299
+ }): any;
300
+ /**
301
+ * The list row shown while an older page loads. Rendered inside the
302
+ * message `<ul>`, so its root must be an `<li>`.
303
+ */
304
+ 'loading-older'?(props: {
305
+ conversation: ChatConversation;
306
+ }): any;
307
+ /** Window body when the first page failed. */
308
+ error?(props: {
309
+ conversation: ChatConversation;
310
+ error: unknown;
311
+ retry: () => void;
312
+ }): any;
313
+ /** Panel text when the filter matches nothing. */
314
+ empty?(): any;
315
+ launcher?(): any;
316
+ /**
317
+ * Replaces the rendered divider while keeping `dateLabel`'s positioning.
318
+ * Whatever you render must be an `<li>`: it is a direct child of the
319
+ * message list's `<ul>`.
320
+ */
321
+ divider?(props: {
322
+ label: string;
323
+ message: ChatMessage;
324
+ previous?: ChatMessage;
325
+ }): any;
326
+ /**
327
+ * Replaces the rendered notice while keeping `noticeLabel`'s decision.
328
+ * Whatever you render must be an `<li>`: it is a direct child of the
329
+ * message list's `<ul>`.
330
+ */
331
+ notice?(props: {
332
+ label: string;
333
+ message: ChatMessage;
334
+ }): any;
335
+ };
@@ -0,0 +1,7 @@
1
+ import { type InjectionKey } from 'vue';
2
+ import type { ChatDockStore } from './messenger-types';
3
+ export declare const chatDockStoreKey: InjectionKey<ChatDockStore>;
4
+ /** Shares a store created with `useChatDock` with the component subtree. */
5
+ export declare function provideChatDock(store: ChatDockStore): void;
6
+ /** The store an ancestor provided, or `undefined` outside one. */
7
+ export declare function injectChatDock(): ChatDockStore | undefined;
@@ -0,0 +1,162 @@
1
+ export type KChatWindowState = 'expanded' | 'railed';
2
+ export type KChatDockProps = {
3
+ /**
4
+ * Capacity floor, so a narrow dock still shows one window rather than
5
+ * nothing but heads. Gap, offset and window dimensions are deliberately not
6
+ * props — they are the CSS variables registered on `.KChatDock`, and the
7
+ * module measures them back rather than being told them twice.
8
+ */
9
+ minWindows?: number;
10
+ };
11
+ export type KChatDockEmits = {
12
+ reflow: [];
13
+ launcher: [];
14
+ /**
15
+ * The panel's write button was clicked. The dock mounts nothing itself —
16
+ * render a `KChatNewWindow` (or anything else) in response.
17
+ */
18
+ compose: [];
19
+ /** After the panel opens or closes. */
20
+ panel: [open: boolean];
21
+ /** After each filter, including the reset when the panel closes. */
22
+ search: [query: string];
23
+ /**
24
+ * An item was picked. `opened` is `true` when the dock expanded an existing
25
+ * `KChatWindow` with that id itself; `false` means the app must mount one.
26
+ */
27
+ select: [id: string, opened: boolean];
28
+ /**
29
+ * A user expanded a railed window from its head, a `+N` popover row, or the
30
+ * window's own toggle. Distinct from `update:state` on the window, which
31
+ * also fires when a reflow un-rails by capacity.
32
+ */
33
+ activate: [id: string];
34
+ };
35
+ export type KChatDockSlots = {
36
+ default?(): any;
37
+ launcher?(): any;
38
+ };
39
+ /**
40
+ * `KChatWindow` teleports its head into the dock's rail, which makes it a
41
+ * multi-root (Fragment) component — unlike every other component in this
42
+ * package. A template `ref` on it resolves `$el` to the fragment's anchor
43
+ * text node, not the window element, so reading DOM properties (e.g.
44
+ * `.classList`) off that ref will throw.
45
+ */
46
+ export type KChatWindowProps = {
47
+ closable?: boolean;
48
+ minimizable?: boolean;
49
+ title?: string;
50
+ unread?: number;
51
+ /**
52
+ * Links this window to its head in the rail. Core reads it from
53
+ * `data-kt-chat-window` to pair the two, so a window without one gets no
54
+ * head — which is legitimate, just headless.
55
+ */
56
+ id?: string;
57
+ };
58
+ export type KChatWindowEmits = {
59
+ close: [];
60
+ };
61
+ export type KChatWindowSlots = {
62
+ actions?(): any;
63
+ /**
64
+ * The fallback for `head` and `row` — a railed head's circle and a `+N`
65
+ * popover row. It does NOT appear in an open window's header: the title
66
+ * already names the conversation there, and the 320px header has the
67
+ * minimize and close controls competing for it.
68
+ */
69
+ avatar?(): any;
70
+ default?(): any;
71
+ /** A railed head's circle. Falls back to `avatar` when not given. */
72
+ head?(): any;
73
+ /**
74
+ * A full-width row under the title and actions, inside the header — e.g.
75
+ * the people search of `KChatNewWindow`. Rendered only when passed.
76
+ */
77
+ search?(): any;
78
+ /** The popover row's avatar. Falls back to `avatar` when not given. */
79
+ row?(): any;
80
+ title?(): any;
81
+ };
82
+ export type KChatNewWindowProps = {
83
+ /** Pairs the window with its rail head, as `KChatWindow`'s `id` does. */
84
+ id?: string;
85
+ title?: string;
86
+ /** People search placeholder. */
87
+ placeholder?: string;
88
+ /** People search's accessible name. Default `'Search people'`. */
89
+ searchLabel?: string;
90
+ };
91
+ export type KChatNewWindowEmits = {
92
+ /** On every keystroke in the people search. */
93
+ search: [query: string];
94
+ close: [];
95
+ };
96
+ export type KChatNewWindowSlots = {
97
+ /** The body under the search: e.g. a "Create New Group" link, suggestions. */
98
+ default?(): any;
99
+ };
100
+ export type KChatDockPanelProps = {
101
+ /** Header text. */
102
+ title?: string;
103
+ /** Search field placeholder. */
104
+ placeholder?: string;
105
+ };
106
+ /**
107
+ * `KChatDockPanel` teleports into the dock's row zone, so it is multi-root
108
+ * like `KChatWindow`: a template `ref` on it resolves `$el` to a fragment
109
+ * anchor, not the panel element.
110
+ */
111
+ export type KChatDockPanelSlots = {
112
+ /** `KChatDockItem`s. */
113
+ default?(): any;
114
+ /**
115
+ * Header controls, between the title and the built-in write, maximize and
116
+ * close buttons — so close stays last in the DOM and in the tab order.
117
+ *
118
+ * Controls here bind their own handlers. Do not put
119
+ * `data-kt-chat-dock-item` on anything in this slot: `KChatDock`'s root
120
+ * click handler routes that attribute as a conversation selection.
121
+ */
122
+ actions?(): any;
123
+ /** Replaces the "No conversations found" text. */
124
+ empty?(): any;
125
+ };
126
+ export type KChatDockItemProps = {
127
+ /** Conversation id, the same page-wide id space as `KChatWindow`'s `id`. */
128
+ id: string;
129
+ name: string;
130
+ /** One-line last-message preview, muted and truncated. */
131
+ preview?: string;
132
+ unread?: number;
133
+ };
134
+ export type KChatDockItemSlots = {
135
+ /** Inside the avatar circle. Falls back to initials from `name`. */
136
+ avatar?(): any;
137
+ /**
138
+ * Replaces the avatar circle entirely, for an app that draws its own — a
139
+ * stack of participant avatars for a group, a presence dot overlaid on the
140
+ * photo. `avatar` fills the built-in circle; this one stands in for it, so
141
+ * use it instead of nesting a circle inside `KAvatar`.
142
+ *
143
+ * Like `trailing`, this renders inside the row's own `<button>`: keep the
144
+ * content non-interactive, or the parser closes the button early and breaks
145
+ * `data-kt-chat-dock-item` click routing for every row after it.
146
+ */
147
+ media?(): any;
148
+ /**
149
+ * After the body, where the unread badge sits. Falls back to that badge, so
150
+ * a row that does not use this slot is unchanged. Replacing the badge does
151
+ * not change the row's accessible name, which still folds in `unread` —
152
+ * keep the two consistent or pass a matching `unread`.
153
+ *
154
+ * This slot renders inside the row's own `<button>` — non-interactive
155
+ * content only (a badge, a timestamp). A nested `<button>` (e.g. a mute
156
+ * control) is invalid HTML: the parser repairs it by closing the outer
157
+ * button early, corrupting the row and breaking
158
+ * `data-kt-chat-dock-item` click routing for everything after it. For a
159
+ * real control, render it outside the row instead.
160
+ */
161
+ trailing?(): any;
162
+ };
@@ -0,0 +1,11 @@
1
+ import type { ChatDockLoaders, ChatDockOptions, ChatDockStore } from './messenger-types';
2
+ /**
3
+ * Owns everything about a dock's conversations except the DOM: which windows
4
+ * are open, each one's messages, cursor, loading state, error and draft, and
5
+ * every call to the app's loaders. `KMessenger` renders it; any component can
6
+ * hold the same instance through `provideChatDock` / `injectChatDock`.
7
+ *
8
+ * Every action is idempotent and safe before the list has loaded. None throws:
9
+ * a loader rejection becomes `error` / `listError` and an `'error'` event.
10
+ */
11
+ export declare function useChatDock(loaders: ChatDockLoaders, options?: ChatDockOptions): ChatDockStore;
@@ -10,16 +10,16 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
10
10
  expand: () => boolean;
11
11
  collapse: () => boolean;
12
12
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ expanded: () => any;
13
14
  collapse: () => any;
14
15
  collapsed: () => any;
15
16
  expand: () => any;
16
- expanded: () => any;
17
17
  "update:expanded": (value: boolean) => any;
18
18
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
19
+ onExpanded?: (() => any) | undefined;
19
20
  onCollapse?: (() => any) | undefined;
20
21
  onCollapsed?: (() => any) | undefined;
21
22
  onExpand?: (() => any) | undefined;
22
- onExpanded?: (() => any) | undefined;
23
23
  "onUpdate:expanded"?: ((value: boolean) => any) | undefined;
24
24
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
25
25
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -10,11 +10,13 @@ export type CollapseSyncOptions = {
10
10
  /**
11
11
  * Two-way binding between a `v-model` and core's Collapse module.
12
12
  *
13
- * `data-kt-collapse` stays on the element, so core's delegated toggle keeps
14
- * working — including `data-kt-collapse-group`, where opening one pane closes
15
- * its siblings through core rather than through Vue. Each sibling hears its own
16
- * `kt.collapse` and updates its own model, so grouping needs no coordination
17
- * here.
13
+ * `data-kt-collapse` stays on the element, so `data-kt-collapse-group` keeps
14
+ * working: opening one pane closes its siblings inside core's `expand()` rather
15
+ * than through Vue. Each sibling hears its own `kt.collapse` and updates its own
16
+ * model, so grouping needs no coordination here.
17
+ *
18
+ * The toggle click is bound below rather than left to core's delegated handler,
19
+ * so a collapse works in an app that never called `Knitify.init()`.
18
20
  *
19
21
  * The guard is `moduleExpanded` — which way the module is actually going —
20
22
  * rather than a flag set around the model write. Vue 3.5 batches reactive
@@ -0,0 +1,26 @@
1
+ import type { KDateInputInvalidReason, KDateInputProps } from './types';
2
+ type __VLS_Props = KDateInputProps;
3
+ type __VLS_ModelProps = {
4
+ modelValue?: Date | null;
5
+ };
6
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
8
+ clear: () => null;
9
+ close: () => void | undefined;
10
+ focus: () => void | undefined;
11
+ open: () => void | undefined;
12
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ open: () => any;
14
+ close: () => any;
15
+ invalid: (reason: KDateInputInvalidReason, text: string) => any;
16
+ clear: () => any;
17
+ "update:modelValue": (value: Date | null) => any;
18
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
19
+ onOpen?: (() => any) | undefined;
20
+ onClose?: (() => any) | undefined;
21
+ onInvalid?: ((reason: KDateInputInvalidReason, text: string) => any) | undefined;
22
+ onClear?: (() => any) | undefined;
23
+ "onUpdate:modelValue"?: ((value: Date | null) => any) | undefined;
24
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;