@icen.ai/ui 0.8.0 → 0.9.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 (228) hide show
  1. package/AGENTS.md +63 -14
  2. package/README.md +17 -9
  3. package/dist/base.css +4 -3
  4. package/dist/behaviors/accordion.d.mts +5 -2
  5. package/dist/behaviors/accordion.mjs +36 -11
  6. package/dist/behaviors/ai-branch.d.mts +19 -0
  7. package/dist/behaviors/ai-branch.mjs +217 -0
  8. package/dist/behaviors/ai-chat.d.mts +11 -7
  9. package/dist/behaviors/ai-chat.mjs +134 -51
  10. package/dist/behaviors/ai-composer.d.mts +28 -3
  11. package/dist/behaviors/ai-composer.mjs +399 -229
  12. package/dist/behaviors/ai-core.d.mts +9 -4
  13. package/dist/behaviors/ai-core.mjs +21 -8
  14. package/dist/behaviors/ai-diff.d.mts +2 -2
  15. package/dist/behaviors/ai-diff.mjs +172 -41
  16. package/dist/behaviors/ai-feedback.d.mts +26 -0
  17. package/dist/behaviors/ai-feedback.mjs +303 -0
  18. package/dist/behaviors/ai-panel.d.mts +26 -9
  19. package/dist/behaviors/ai-panel.mjs +211 -110
  20. package/dist/behaviors/ai-provider.mjs +54 -48
  21. package/dist/behaviors/ai-threads.d.mts +38 -0
  22. package/dist/behaviors/ai-threads.mjs +319 -0
  23. package/dist/behaviors/ai-tool.d.mts +12 -4
  24. package/dist/behaviors/ai-tool.mjs +316 -263
  25. package/dist/behaviors/ai-tools.d.mts +9 -6
  26. package/dist/behaviors/ai-tools.mjs +264 -155
  27. package/dist/behaviors/back-top.mjs +16 -1
  28. package/dist/behaviors/carousel.d.mts +5 -2
  29. package/dist/behaviors/carousel.mjs +53 -26
  30. package/dist/behaviors/charts.d.mts +170 -22
  31. package/dist/behaviors/charts.mjs +1016 -150
  32. package/dist/behaviors/command-palette.d.mts +40 -6
  33. package/dist/behaviors/command-palette.mjs +143 -15
  34. package/dist/behaviors/context-menu.d.mts +21 -4
  35. package/dist/behaviors/context-menu.mjs +122 -38
  36. package/dist/behaviors/controls.d.mts +59 -0
  37. package/dist/behaviors/controls.mjs +601 -0
  38. package/dist/behaviors/copy.d.mts +5 -2
  39. package/dist/behaviors/copy.mjs +37 -12
  40. package/dist/behaviors/datatable.d.mts +12 -0
  41. package/dist/behaviors/datatable.mjs +226 -43
  42. package/dist/behaviors/date-picker.d.mts +2 -2
  43. package/dist/behaviors/date-picker.mjs +171 -32
  44. package/dist/behaviors/dropdown.d.mts +6 -2
  45. package/dist/behaviors/dropdown.mjs +164 -25
  46. package/dist/behaviors/events.d.mts +523 -0
  47. package/dist/behaviors/events.mjs +208 -0
  48. package/dist/behaviors/input.mjs +25 -12
  49. package/dist/behaviors/kb-access.d.mts +34 -0
  50. package/dist/behaviors/kb-access.mjs +569 -0
  51. package/dist/behaviors/kb-acl.d.mts +50 -0
  52. package/dist/behaviors/kb-acl.mjs +405 -0
  53. package/dist/behaviors/kb-answer.d.mts +38 -0
  54. package/dist/behaviors/kb-answer.mjs +2055 -0
  55. package/dist/behaviors/kb-audit.d.mts +23 -0
  56. package/dist/behaviors/kb-audit.mjs +375 -0
  57. package/dist/behaviors/kb-canvas.d.mts +44 -0
  58. package/dist/behaviors/kb-canvas.mjs +589 -0
  59. package/dist/behaviors/kb-chain.d.mts +15 -0
  60. package/dist/behaviors/kb-chain.mjs +270 -0
  61. package/dist/behaviors/kb-checkpoint.d.mts +16 -0
  62. package/dist/behaviors/kb-checkpoint.mjs +342 -0
  63. package/dist/behaviors/kb-chunks.d.mts +31 -0
  64. package/dist/behaviors/kb-chunks.mjs +475 -0
  65. package/dist/behaviors/kb-citation.d.mts +38 -0
  66. package/dist/behaviors/kb-citation.mjs +677 -0
  67. package/dist/behaviors/kb-clarify.d.mts +20 -0
  68. package/dist/behaviors/kb-clarify.mjs +248 -0
  69. package/dist/behaviors/kb-conflict.d.mts +22 -0
  70. package/dist/behaviors/kb-conflict.mjs +284 -0
  71. package/dist/behaviors/kb-connector.d.mts +17 -0
  72. package/dist/behaviors/kb-connector.mjs +375 -0
  73. package/dist/behaviors/kb-core.d.mts +529 -0
  74. package/dist/behaviors/kb-core.mjs +890 -0
  75. package/dist/behaviors/kb-eval.d.mts +22 -0
  76. package/dist/behaviors/kb-eval.mjs +408 -0
  77. package/dist/behaviors/kb-explain.d.mts +11 -0
  78. package/dist/behaviors/kb-explain.mjs +243 -0
  79. package/dist/behaviors/kb-filter.d.mts +31 -0
  80. package/dist/behaviors/kb-filter.mjs +587 -0
  81. package/dist/behaviors/kb-gap.d.mts +27 -0
  82. package/dist/behaviors/kb-gap.mjs +273 -0
  83. package/dist/behaviors/kb-hittest.d.mts +34 -0
  84. package/dist/behaviors/kb-hittest.mjs +409 -0
  85. package/dist/behaviors/kb-metadata.d.mts +29 -0
  86. package/dist/behaviors/kb-metadata.mjs +326 -0
  87. package/dist/behaviors/kb-passage.d.mts +41 -0
  88. package/dist/behaviors/kb-passage.mjs +529 -0
  89. package/dist/behaviors/kb-pipeline.d.mts +18 -0
  90. package/dist/behaviors/kb-pipeline.mjs +381 -0
  91. package/dist/behaviors/kb-qa.d.mts +26 -0
  92. package/dist/behaviors/kb-qa.mjs +332 -0
  93. package/dist/behaviors/kb-rerank.d.mts +20 -0
  94. package/dist/behaviors/kb-rerank.mjs +315 -0
  95. package/dist/behaviors/kb-retrieval.d.mts +49 -0
  96. package/dist/behaviors/kb-retrieval.mjs +746 -0
  97. package/dist/behaviors/kb-review.d.mts +44 -0
  98. package/dist/behaviors/kb-review.mjs +451 -0
  99. package/dist/behaviors/kb-sandbox.d.mts +33 -0
  100. package/dist/behaviors/kb-sandbox.mjs +325 -0
  101. package/dist/behaviors/kb-segment.d.mts +32 -0
  102. package/dist/behaviors/kb-segment.mjs +499 -0
  103. package/dist/behaviors/kb-sources.d.mts +27 -0
  104. package/dist/behaviors/kb-sources.mjs +373 -0
  105. package/dist/behaviors/kb-sql.d.mts +43 -0
  106. package/dist/behaviors/kb-sql.mjs +948 -0
  107. package/dist/behaviors/kb-trace.d.mts +16 -0
  108. package/dist/behaviors/kb-trace.mjs +414 -0
  109. package/dist/behaviors/kb-visibility.d.mts +44 -0
  110. package/dist/behaviors/kb-visibility.mjs +403 -0
  111. package/dist/behaviors/kb-who-can.d.mts +32 -0
  112. package/dist/behaviors/kb-who-can.mjs +379 -0
  113. package/dist/behaviors/modal.d.mts +24 -5
  114. package/dist/behaviors/modal.mjs +76 -10
  115. package/dist/behaviors/nav.d.mts +1 -1
  116. package/dist/behaviors/nav.mjs +33 -7
  117. package/dist/behaviors/notification.d.mts +20 -4
  118. package/dist/behaviors/notification.mjs +53 -73
  119. package/dist/behaviors/popover.d.mts +39 -3
  120. package/dist/behaviors/popover.mjs +90 -4
  121. package/dist/behaviors/select.d.mts +4 -2
  122. package/dist/behaviors/select.mjs +161 -24
  123. package/dist/behaviors/sidebar.d.mts +5 -2
  124. package/dist/behaviors/sidebar.mjs +43 -13
  125. package/dist/behaviors/slider.d.mts +5 -2
  126. package/dist/behaviors/slider.mjs +54 -43
  127. package/dist/behaviors/split-pane.d.mts +6 -2
  128. package/dist/behaviors/split-pane.mjs +62 -21
  129. package/dist/behaviors/tabs.d.mts +3 -2
  130. package/dist/behaviors/tabs.mjs +65 -14
  131. package/dist/behaviors/tag-input.d.mts +5 -2
  132. package/dist/behaviors/tag-input.mjs +61 -21
  133. package/dist/behaviors/theme.d.mts +13 -2
  134. package/dist/behaviors/theme.mjs +48 -4
  135. package/dist/behaviors/toast.d.mts +30 -8
  136. package/dist/behaviors/toast.mjs +74 -7
  137. package/dist/behaviors/tree.d.mts +5 -2
  138. package/dist/behaviors/tree.mjs +38 -15
  139. package/dist/behaviors/upload.mjs +21 -23
  140. package/dist/cli.mjs +1 -1
  141. package/dist/components/ai-branch.mjs +3 -0
  142. package/dist/components/ai-chat.css +295 -0
  143. package/dist/components/ai-feedback.mjs +3 -0
  144. package/dist/components/ai-panel.css +218 -1
  145. package/dist/components/ai-threads.mjs +3 -0
  146. package/dist/components/ai-tool-call.mjs +1 -1
  147. package/dist/components/badge.css +1 -1
  148. package/dist/components/breadcrumb.css +0 -32
  149. package/dist/components/chart-calendar.mjs +1 -2
  150. package/dist/components/chart-graph.css +57 -0
  151. package/dist/components/chart-graph.mjs +4 -0
  152. package/dist/components/chart-map.mjs +3 -0
  153. package/dist/components/chart-pie.css +0 -6
  154. package/dist/components/chart-scatter.mjs +1 -1
  155. package/dist/components/charts.css +33 -1
  156. package/dist/components/charts.mjs +1 -0
  157. package/dist/components/content.css +3 -16
  158. package/dist/components/datatable.css +1 -1
  159. package/dist/components/date-picker.css +1 -1
  160. package/dist/components/kb-access.mjs +4 -0
  161. package/dist/components/kb-acl.mjs +4 -0
  162. package/dist/components/kb-agent.css +481 -0
  163. package/dist/components/kb-answer.mjs +4 -0
  164. package/dist/components/kb-audit.mjs +4 -0
  165. package/dist/components/kb-canvas.mjs +4 -0
  166. package/dist/components/kb-chain.mjs +4 -0
  167. package/dist/components/kb-checkpoint.mjs +4 -0
  168. package/dist/components/kb-chunks.mjs +4 -0
  169. package/dist/components/kb-citation.mjs +4 -0
  170. package/dist/components/kb-clarify.mjs +4 -0
  171. package/dist/components/kb-conflict.mjs +4 -0
  172. package/dist/components/kb-connector.mjs +4 -0
  173. package/dist/components/kb-data.css +649 -0
  174. package/dist/components/kb-eval.mjs +4 -0
  175. package/dist/components/kb-explain.mjs +4 -0
  176. package/dist/components/kb-filter.mjs +4 -0
  177. package/dist/components/kb-gap.mjs +4 -0
  178. package/dist/components/kb-ground.css +566 -0
  179. package/dist/components/kb-hittest.mjs +4 -0
  180. package/dist/components/kb-ingest.css +898 -0
  181. package/dist/components/kb-metadata.mjs +4 -0
  182. package/dist/components/kb-ops.css +548 -0
  183. package/dist/components/kb-passage.mjs +4 -0
  184. package/dist/components/kb-perm.css +444 -0
  185. package/dist/components/kb-pipeline.mjs +4 -0
  186. package/dist/components/kb-qa.mjs +4 -0
  187. package/dist/components/kb-rerank.mjs +4 -0
  188. package/dist/components/kb-retrieval.mjs +4 -0
  189. package/dist/components/kb-review.mjs +4 -0
  190. package/dist/components/kb-sandbox.mjs +4 -0
  191. package/dist/components/kb-search.css +940 -0
  192. package/dist/components/kb-segment.mjs +4 -0
  193. package/dist/components/kb-sources.mjs +4 -0
  194. package/dist/components/kb-sql.mjs +4 -0
  195. package/dist/components/kb-trace.mjs +4 -0
  196. package/dist/components/kb-visibility.mjs +4 -0
  197. package/dist/components/kb-who-can.mjs +4 -0
  198. package/dist/components/kb.css +252 -0
  199. package/dist/components/kb.mjs +9 -0
  200. package/dist/components/notification.css +2 -3
  201. package/dist/components/pagination.css +3 -1
  202. package/dist/components/pagination.mjs +1 -0
  203. package/dist/components/rating.mjs +1 -0
  204. package/dist/components/segmented.css +9 -1
  205. package/dist/components/segmented.mjs +1 -1
  206. package/dist/components/select.css +67 -4
  207. package/dist/components/steps.css +13 -3
  208. package/dist/components/steps.mjs +1 -0
  209. package/dist/components/switch.css +3 -1
  210. package/dist/components/switch.mjs +1 -0
  211. package/dist/components/table.mjs +1 -0
  212. package/dist/components/tabs.css +23 -0
  213. package/dist/components/tag-input.css +1 -6
  214. package/dist/components/upload.css +0 -15
  215. package/dist/index.d.mts +48 -11
  216. package/dist/index.mjs +13205 -3615
  217. package/dist/registry.json +366 -15
  218. package/dist/retro-effects.css +3 -16
  219. package/dist/tokens/retro-effects.css +3 -16
  220. package/dist/tokens/style-profiles.css +3 -2
  221. package/dist/tokens/typography.css +2 -0
  222. package/dist/tokens.css +5 -2
  223. package/dist/ui.css +5713 -267
  224. package/docs/research/2026-10-03-ai-kb-components.md +392 -0
  225. package/docs/research/2026-10-03-kb-permissions.md +992 -0
  226. package/docs/spec/ai-native.md +7 -4
  227. package/docs/spec/kb-family.md +443 -0
  228. package/package.json +2 -2
@@ -0,0 +1,208 @@
1
+ // src/behaviors/events.ts
2
+ function onIcen(type, a, b, c) {
3
+ if (typeof document === "undefined") return () => {
4
+ };
5
+ const selector = typeof a === "string" ? a : null;
6
+ const handler = selector ? b : a;
7
+ const opts = selector ? c : b;
8
+ const within = opts?.within ?? document;
9
+ const once = opts?.once === true;
10
+ let off = () => {
11
+ };
12
+ const fn = (e) => {
13
+ const broadcast = !(e.target instanceof Element);
14
+ if (selector) {
15
+ if (broadcast) return;
16
+ const detail = e.detail;
17
+ const src = detail?.source instanceof Element ? detail.source : e.target;
18
+ if (!(src instanceof Element) || !src.closest(selector)) return;
19
+ }
20
+ handler(e);
21
+ if (once) off();
22
+ };
23
+ within.addEventListener(type, fn);
24
+ off = () => {
25
+ within.removeEventListener(type, fn);
26
+ opts?.signal?.removeEventListener("abort", off);
27
+ };
28
+ if (opts?.signal) {
29
+ if (opts.signal.aborted) {
30
+ off();
31
+ return () => {
32
+ };
33
+ }
34
+ opts.signal.addEventListener("abort", off, { once: true });
35
+ }
36
+ return off;
37
+ }
38
+ function emitIcen(source, type, detail) {
39
+ return source.dispatchEvent(
40
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
41
+ );
42
+ }
43
+ var policies = /* @__PURE__ */ new Map();
44
+ function setEventPolicy(type, policy) {
45
+ if (policy) policies.set(type, policy);
46
+ else policies.delete(type);
47
+ }
48
+ function getEventPolicy(type) {
49
+ return policies.get(type);
50
+ }
51
+ function resetEventPolicies() {
52
+ policies.clear();
53
+ }
54
+ var LONGPRESS_MS = 520;
55
+ var LONGPRESS_MOVE = 12;
56
+ var CLICK_DELAY = 220;
57
+ var CLICK_DRAG_TOLERANCE = 5;
58
+ function gestureHost(e, name) {
59
+ const t = e.target;
60
+ if (!(t instanceof Element)) return null;
61
+ return t.closest(`[data-gestures~="${name}"]`);
62
+ }
63
+ function pointOf(e) {
64
+ return e instanceof MouseEvent || typeof PointerEvent !== "undefined" && e instanceof PointerEvent ? { x: e.clientX, y: e.clientY } : { x: 0, y: 0 };
65
+ }
66
+ function emit(host, type, originalEvent, text) {
67
+ const { x, y } = pointOf(originalEvent);
68
+ const detail = { source: host, originalEvent, x, y };
69
+ if (text != null) detail.text = text;
70
+ const ev = new CustomEvent(type, {
71
+ detail,
72
+ bubbles: true,
73
+ composed: true,
74
+ cancelable: true
75
+ });
76
+ const delivered = host.dispatchEvent(ev);
77
+ if (delivered) policies.get(type)?.(ev);
78
+ return ev;
79
+ }
80
+ var gesturesInit = false;
81
+ var gesturesTeardown = null;
82
+ function initGestures() {
83
+ if (gesturesInit || typeof document === "undefined") return () => {
84
+ };
85
+ gesturesInit = true;
86
+ let clickTimer = null;
87
+ let pending = null;
88
+ let downPos = null;
89
+ let suppressTrailingClick = false;
90
+ const cancelPendingClick = () => {
91
+ if (clickTimer) clearTimeout(clickTimer);
92
+ clickTimer = null;
93
+ pending = null;
94
+ };
95
+ const onDownPos = (e) => {
96
+ downPos = { x: e.clientX, y: e.clientY };
97
+ suppressTrailingClick = false;
98
+ };
99
+ const isDragRelease = (e) => downPos != null && Math.hypot(e.clientX - downPos.x, e.clientY - downPos.y) > CLICK_DRAG_TOLERANCE;
100
+ const onClick = (e) => {
101
+ const host = gestureHost(e, "click");
102
+ if (!host) return;
103
+ if (suppressTrailingClick) {
104
+ suppressTrailingClick = false;
105
+ return;
106
+ }
107
+ if (isDragRelease(e)) return;
108
+ if (host.matches('[data-gestures~="dblclick"]')) {
109
+ if (clickTimer) clearTimeout(clickTimer);
110
+ pending = { host, e };
111
+ clickTimer = setTimeout(() => {
112
+ clickTimer = null;
113
+ const p = pending;
114
+ pending = null;
115
+ if (p) emit(p.host, "icen:click", p.e);
116
+ }, CLICK_DELAY);
117
+ } else {
118
+ emit(host, "icen:click", e);
119
+ }
120
+ };
121
+ const onDblClick = (e) => {
122
+ const host = gestureHost(e, "dblclick");
123
+ if (!host) return;
124
+ cancelPendingClick();
125
+ if (isDragRelease(e)) return;
126
+ emit(host, "icen:dblclick", e);
127
+ };
128
+ const onContextMenu = (e) => {
129
+ const host = gestureHost(e, "contextmenu");
130
+ if (!host) return;
131
+ const hasPolicy = policies.has("icen:contextmenu");
132
+ const ev = emit(host, "icen:contextmenu", e);
133
+ if (ev.defaultPrevented || hasPolicy) e.preventDefault();
134
+ };
135
+ let lp = null;
136
+ const clearLp = () => {
137
+ if (lp) clearTimeout(lp.timer);
138
+ lp = null;
139
+ };
140
+ const onLpDown = (e) => {
141
+ const host = gestureHost(e, "longpress");
142
+ if (!host) return;
143
+ clearLp();
144
+ lp = {
145
+ host,
146
+ e,
147
+ x: e.clientX,
148
+ y: e.clientY,
149
+ timer: setTimeout(() => {
150
+ const cur = lp;
151
+ lp = null;
152
+ if (cur) {
153
+ suppressTrailingClick = true;
154
+ emit(cur.host, "icen:longpress", cur.e);
155
+ }
156
+ }, LONGPRESS_MS)
157
+ };
158
+ };
159
+ const onLpMove = (e) => {
160
+ if (!lp) return;
161
+ if (Math.hypot(e.clientX - lp.x, e.clientY - lp.y) > LONGPRESS_MOVE) clearLp();
162
+ };
163
+ const onTextSelect = (e) => {
164
+ const host = gestureHost(e, "text-select");
165
+ if (!host) return;
166
+ const sel = window.getSelection();
167
+ const text = sel?.toString() ?? "";
168
+ if (!text.trim() || !sel || !host.contains(sel.anchorNode)) return;
169
+ emit(host, "icen:text-select", e, text);
170
+ };
171
+ document.addEventListener("pointerdown", onDownPos);
172
+ document.addEventListener("click", onClick);
173
+ document.addEventListener("dblclick", onDblClick);
174
+ document.addEventListener("contextmenu", onContextMenu);
175
+ document.addEventListener("pointerdown", onLpDown);
176
+ document.addEventListener("pointermove", onLpMove);
177
+ document.addEventListener("pointerup", clearLp);
178
+ document.addEventListener("pointercancel", clearLp);
179
+ document.addEventListener("mouseup", onTextSelect);
180
+ gesturesTeardown = () => {
181
+ document.removeEventListener("pointerdown", onDownPos);
182
+ document.removeEventListener("click", onClick);
183
+ document.removeEventListener("dblclick", onDblClick);
184
+ document.removeEventListener("contextmenu", onContextMenu);
185
+ document.removeEventListener("pointerdown", onLpDown);
186
+ document.removeEventListener("pointermove", onLpMove);
187
+ document.removeEventListener("pointerup", clearLp);
188
+ document.removeEventListener("pointercancel", clearLp);
189
+ document.removeEventListener("mouseup", onTextSelect);
190
+ cancelPendingClick();
191
+ clearLp();
192
+ gesturesInit = false;
193
+ gesturesTeardown = null;
194
+ };
195
+ return gesturesTeardown;
196
+ }
197
+ function destroyGestures() {
198
+ gesturesTeardown?.();
199
+ }
200
+ export {
201
+ destroyGestures,
202
+ emitIcen,
203
+ getEventPolicy,
204
+ initGestures,
205
+ onIcen,
206
+ resetEventPolicies,
207
+ setEventPolicy
208
+ };
@@ -1,12 +1,20 @@
1
+ // src/behaviors/events.ts
2
+ function emitIcen(source, type, detail) {
3
+ return source.dispatchEvent(
4
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
5
+ );
6
+ }
7
+
1
8
  // src/behaviors/input.ts
2
- var isComposing = false;
3
- if (typeof document !== "undefined") {
4
- document.addEventListener("compositionstart", () => {
5
- isComposing = true;
9
+ function trackComposing(target) {
10
+ let composing = false;
11
+ target.addEventListener("compositionstart", () => {
12
+ composing = true;
6
13
  });
7
- document.addEventListener("compositionend", () => {
8
- isComposing = false;
14
+ target.addEventListener("compositionend", () => {
15
+ composing = false;
9
16
  });
17
+ return () => composing;
10
18
  }
11
19
  function setupClear(wrap) {
12
20
  const btn = wrap.querySelector(".input-clear");
@@ -58,7 +66,6 @@ function setupCounter(field) {
58
66
  const maxAttr = field.getAttribute("maxlength");
59
67
  const dataCount = field.getAttribute("data-count");
60
68
  if (!maxAttr && dataCount === null) return;
61
- el.__icenCounterInit = true;
62
69
  const max = maxAttr ? Number(maxAttr) : 0;
63
70
  let counter = null;
64
71
  const wrap = field.closest(".input-wrap, .textarea-wrap");
@@ -75,6 +82,8 @@ function setupCounter(field) {
75
82
  }
76
83
  const counterEl = counter;
77
84
  if (!counterEl) return;
85
+ el.__icenCounterInit = true;
86
+ const isComposing = trackComposing(field);
78
87
  function update() {
79
88
  const len = field.value.length;
80
89
  counterEl.textContent = max > 0 ? `${len} / ${max}` : `${len}`;
@@ -85,8 +94,9 @@ function setupCounter(field) {
85
94
  else if (ratio >= 0.8) counterEl.classList.add("is-warn");
86
95
  }
87
96
  }
97
+ ;
88
98
  field.addEventListener("input", () => {
89
- if (!isComposing) update();
99
+ if (!isComposing()) update();
90
100
  });
91
101
  update();
92
102
  }
@@ -96,6 +106,7 @@ function setupMask(field) {
96
106
  const mask = field.getAttribute("data-mask");
97
107
  if (!mask) return;
98
108
  el.__icenMaskInit = true;
109
+ const isComposing = trackComposing(field);
99
110
  const maskChars = [];
100
111
  for (const ch of mask) maskChars.push(ch);
101
112
  function isInputSlot(ch) {
@@ -137,7 +148,7 @@ function setupMask(field) {
137
148
  field.value = lastFormatted;
138
149
  field.setAttribute("data-raw-value", extractRaw(lastFormatted));
139
150
  field.addEventListener("input", () => {
140
- if (isComposing) return;
151
+ if (isComposing()) return;
141
152
  const cursorPos = field.selectionStart ?? 0;
142
153
  const oldRaw = extractRaw(lastFormatted);
143
154
  const newFull = field.value;
@@ -165,7 +176,7 @@ function setupMask(field) {
165
176
  field.setSelectionRange(targetCursor, targetCursor);
166
177
  });
167
178
  field.addEventListener("keydown", (ev) => {
168
- if (isComposing) return;
179
+ if (isComposing()) return;
169
180
  if (ev.ctrlKey || ev.metaKey || ev.altKey) return;
170
181
  if (["Backspace", "Delete", "Tab", "Escape", "ArrowLeft", "ArrowRight", "Home", "End", "Enter"].includes(ev.key)) return;
171
182
  const currentRaw = extractRaw(field.value);
@@ -195,6 +206,7 @@ function setupOtp(group) {
195
206
  const el = group;
196
207
  if (el.__icenInputInit) return;
197
208
  el.__icenInputInit = true;
209
+ const isComposing = trackComposing(group);
198
210
  const cells = Array.from(group.querySelectorAll(".otp-cell"));
199
211
  const syncFilled = (cell) => {
200
212
  cell.classList.toggle("is-filled", cell.value.length > 0);
@@ -205,7 +217,7 @@ function setupOtp(group) {
205
217
  }
206
218
  syncFilled(cell);
207
219
  cell.addEventListener("input", () => {
208
- if (isComposing) return;
220
+ if (isComposing()) return;
209
221
  const ch = cell.value.slice(-1);
210
222
  cell.value = ch;
211
223
  syncFilled(cell);
@@ -239,7 +251,8 @@ function setupOtp(group) {
239
251
  const fireComplete = () => {
240
252
  const code = cells.map((c) => c.value).join("");
241
253
  if (code.length === cells.length && cells.every((c) => c.value.length > 0)) {
242
- group.dispatchEvent(new CustomEvent("icen:otp-complete", { detail: { code }, bubbles: true }));
254
+ group.classList.add("is-complete");
255
+ emitIcen(group, "icen:otp-complete", { code });
243
256
  group.dispatchEvent(new CustomEvent("otp:complete", { detail: { code }, bubbles: true }));
244
257
  }
245
258
  };
@@ -0,0 +1,34 @@
1
+ import { KbAccessRequest, KbAccessState, KbRole } from './kb-core.js';
2
+ import './ai-core.js';
3
+
4
+ /** createKbAccess 入参(spec §9.3;request 宽进——素对象经 normalizeAccessRequest 归一) */
5
+ interface KbAccessOpts {
6
+ /** 当前访问请求(内部持有副本,不打脏调用方数据) */
7
+ request: KbAccessRequest | Record<string, unknown>;
8
+ /** requester = 申请人视角(被拒五件套 + 表单);approver = 审批人视角(队列卡)。缺省 requester */
9
+ mode?: 'requester' | 'approver';
10
+ /** 表单提交回调(与 icen:kb-access-request 双通道) */
11
+ onRequest?: (r: KbAccessRequest) => void;
12
+ /** 审批决定回调(与 icen:kb-access-decide 双通道;approve 时 role = 批准档位) */
13
+ onDecide?: (id: string, decision: 'approve' | 'deny', role?: KbRole) => void;
14
+ /** 被拒原因文案(缺省固定模板「此内容仅对授权者开放」——不给受限侧任何更多信息,§9.0.3) */
15
+ deniedHint?: string;
16
+ /** 切换身份回调(宿主关注:切换固定身份集重查权限;不派库事件) */
17
+ onSwitchIdentity?: () => void;
18
+ }
19
+ /** createKbAccess 句柄(函数名冻结于 spec §9.3) */
20
+ interface KbAccessHandle {
21
+ /** 合并更新请求字段(Partial)或整体切状态(单字符串);带过期时间的 granted 会即时派生 expired */
22
+ setState(next: Partial<KbAccessRequest> | KbAccessState): void;
23
+ /** 当前请求(normalize 后的副本;外部修改不影响内部) */
24
+ getState(): KbAccessRequest;
25
+ /** 清空 DOM 与标记(幂等;同一 el 重复 create 会先销毁旧实例) */
26
+ destroy(): void;
27
+ }
28
+ /**
29
+ * 创建访问申请流(requester:被拒五件套 + 表单 + 状态徽章族;approver:审批队列卡)。
30
+ * 快照渲染:setState / 表单交互后整树重建(重建前回填用户已输入的理由/时长,不打断打字)。
31
+ */
32
+ declare function createKbAccess(el: HTMLElement, opts: KbAccessOpts): KbAccessHandle;
33
+
34
+ export { type KbAccessHandle, type KbAccessOpts, createKbAccess };