@floegence/floe-webapp-core 0.90.12 → 0.91.1

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.
@@ -1,4 +1,4 @@
1
- import { createComponent as c, mergeProps as R, insert as o, spread as te, memo as K, effect as P, use as le, setAttribute as m, className as ve, template as w, delegateEvents as ge } from "solid-js/web";
1
+ import { createComponent as c, mergeProps as I, insert as o, spread as te, memo as z, effect as P, use as le, setAttribute as m, className as ve, template as w, delegateEvents as ge } from "solid-js/web";
2
2
  import { createUniqueId as me, createSignal as B, createMemo as he, createEffect as N, untrack as be, onCleanup as ae, onMount as ye, Show as V, For as Q } from "solid-js";
3
3
  import { cn as re } from "../../utils/cn.js";
4
4
  import { useFloeLocale as we } from "../../context/LocaleContext.js";
@@ -7,32 +7,32 @@ import { SurfaceFloatingLayer as xe } from "./SurfaceFloatingLayer.js";
7
7
  import { createFloatingPresence as ke } from "./floatingPresence.js";
8
8
  import { calculateMenuPosition as Ve } from "./menuUtils.js";
9
9
  import { useFormControl as Le, joinAriaIds as Oe } from "./formFieldContext.js";
10
- import { createControllableValue as M } from "./controllable.js";
10
+ import { createControllableValue as K } from "./controllable.js";
11
11
  import { ChevronDown as $e, Check as Ee } from "../icons/index.js";
12
12
  import { resolveSurfacePortalBoundaryRect as De, resolveSurfacePortalHost as Pe } from "./dialogSurfaceScope.js";
13
- var Se = /* @__PURE__ */ w("<input>"), _e = /* @__PURE__ */ w("<option value>"), qe = /* @__PURE__ */ w('<div role=status class="px-2 py-2 text-caption">'), Ae = /* @__PURE__ */ w("<button type=button>"), Fe = /* @__PURE__ */ w('<div role=alert class="p-2 text-error">'), Te = /* @__PURE__ */ w('<div role=status class="p-2 text-caption">'), Be = /* @__PURE__ */ w('<div class="floe-floating-presence floe-floating-menu rounded-panel border border-[var(--floe-line)] bg-popover text-popover-foreground shadow-[var(--floe-elevation-float)] p-1"data-floe-surface=floating><div role=listbox class="max-h-64 overflow-y-auto"data-floe-local-interaction-surface=true>'), Re = /* @__PURE__ */ w('<div class="relative min-w-0"><select tabindex=-1 aria-hidden=true class="sr-only pointer-events-none">'), Ie = /* @__PURE__ */ w("<button><span class=truncate>"), Ke = /* @__PURE__ */ w("<option selected>"), Me = /* @__PURE__ */ w("<option>"), He = /* @__PURE__ */ w('<div role=option><span class="h-3.5 w-3.5 shrink-0">');
13
+ var Se = /* @__PURE__ */ w("<input>"), _e = /* @__PURE__ */ w("<option value>"), qe = /* @__PURE__ */ w('<div role=status class="px-2 py-2 text-caption">'), Ae = /* @__PURE__ */ w("<button type=button>"), Fe = /* @__PURE__ */ w('<div role=alert class="p-2 text-error">'), Te = /* @__PURE__ */ w('<div role=status class="p-2 text-caption">'), Be = /* @__PURE__ */ w('<div class="floe-floating-presence floe-floating-menu rounded-panel border border-[var(--floe-line)] bg-popover text-popover-foreground shadow-[var(--floe-elevation-float)] p-1"data-floe-surface=floating><div role=listbox class="max-h-64 overflow-y-auto"data-floe-local-interaction-surface=true>'), Ie = /* @__PURE__ */ w('<div class="relative min-w-0"><select tabindex=-1 aria-hidden=true class="sr-only pointer-events-none">'), Re = /* @__PURE__ */ w("<button><span class=truncate>"), ze = /* @__PURE__ */ w("<option selected>"), Ke = /* @__PURE__ */ w("<option>"), Me = /* @__PURE__ */ w('<div role=option><span class="h-3.5 w-3.5 shrink-0">');
14
14
  function U(e) {
15
- const u = we(), g = Le(), b = me(), W = () => e.id ?? g.id ?? "select-" + b, S = "options-" + b, _ = () => e.disabled ?? g.disabled, q = () => e.readOnly ?? g.readOnly, [h, ne] = M({
15
+ const u = we(), g = Le(), b = me(), W = () => e.id ?? g.id ?? "select-" + b, S = "options-" + b, _ = () => e.disabled ?? g.disabled, q = () => e.readOnly ?? g.readOnly, [h, ne] = K({
16
16
  value: () => e.open,
17
17
  defaultValue: e.defaultOpen ?? !1,
18
18
  onChange: (t) => e.onOpenChange?.(t)
19
- }), [H, G] = B(""), [L, E] = B(-1), [ie, oe] = B({
19
+ }), [M, G] = B(""), [L, E] = B(-1), [ie, oe] = B({
20
20
  x: 0,
21
21
  y: 0
22
22
  }), [ue, de] = B(200);
23
- let x, O, k, I;
23
+ let x, O, k, R;
24
24
  const D = ke({
25
25
  open: h,
26
26
  element: () => k
27
27
  }), [se, ce] = B("bottom");
28
- let j = "", J = 0;
28
+ let H = "", J = 0;
29
29
  const C = he(() => {
30
- if (!e.searchable || e.filter === !1 || !H()) return e.options;
31
- const t = H().toLocaleLowerCase(u.locale);
30
+ if (!e.searchable || e.filter === !1 || !M()) return e.options;
31
+ const t = M().toLocaleLowerCase(u.locale);
32
32
  return e.options.filter((a) => [a.label, ...a.keywords ?? []].some((i) => i.toLocaleLowerCase(u.locale).includes(t)));
33
33
  }), X = () => e.values.map((t) => e.options.find((a) => a.value === t)?.label ?? t).join(", "), y = (t) => {
34
34
  t && (_() || q()) || (ne(t), t || G(""));
35
- }, z = (t) => {
35
+ }, j = (t) => {
36
36
  _() || q() || t.disabled || (e.onValuesChange(e.multiple ? e.values.includes(t.value) ? e.values.filter((a) => a !== t.value) : [...e.values, t.value] : [t.value]), e.multiple || y(!1), x?.focus({
37
37
  preventScroll: !0
38
38
  }));
@@ -55,7 +55,7 @@ function U(e) {
55
55
  })), i = Ve(
56
56
  t,
57
57
  // The position layer is never transformed; motion belongs to its child.
58
- I?.getBoundingClientRect() ?? k.getBoundingClientRect(),
58
+ R?.getBoundingClientRect() ?? k.getBoundingClientRect(),
59
59
  u.direction === "rtl" ? "end" : "start",
60
60
  a
61
61
  );
@@ -78,7 +78,7 @@ function U(e) {
78
78
  };
79
79
  a();
80
80
  const i = new ResizeObserver(a);
81
- x && i.observe(x), I && i.observe(I), window.addEventListener("resize", a), window.addEventListener("scroll", a, !0), ae(() => {
81
+ x && i.observe(x), R && i.observe(R), window.addEventListener("resize", a), window.addEventListener("scroll", a, !0), ae(() => {
82
82
  cancelAnimationFrame(t), i.disconnect(), window.removeEventListener("resize", a), window.removeEventListener("scroll", a, !0);
83
83
  });
84
84
  }), Ce({
@@ -175,14 +175,14 @@ function U(e) {
175
175
  return;
176
176
  }
177
177
  if (t.key === "Enter" || !e.searchable && t.key === " ") {
178
- t.preventDefault(), h() && C()[L()] ? z(C()[L()]) : y(!0);
178
+ t.preventDefault(), h() && C()[L()] ? j(C()[L()]) : y(!0);
179
179
  return;
180
180
  }
181
181
  if (!e.searchable && t.key.length === 1 && !t.ctrlKey && !t.metaKey && !t.altKey) {
182
182
  const a = Date.now();
183
- j = a - J > 700 ? t.key : j + t.key, J = a;
184
- const i = e.options.find((l) => !l.disabled && l.label.toLocaleLowerCase(u.locale).startsWith(j.toLocaleLowerCase(u.locale)));
185
- i && (t.preventDefault(), h() ? E(C().indexOf(i)) : z(i));
183
+ H = a - J > 700 ? t.key : H + t.key, J = a;
184
+ const i = e.options.find((l) => !l.disabled && l.label.toLocaleLowerCase(u.locale).startsWith(H.toLocaleLowerCase(u.locale)));
185
+ i && (t.preventDefault(), h() ? E(C().indexOf(i)) : j(i));
186
186
  }
187
187
  }
188
188
  },
@@ -191,15 +191,15 @@ function U(e) {
191
191
  }
192
192
  };
193
193
  return (() => {
194
- var t = Re(), a = t.firstChild;
194
+ var t = Ie(), a = t.firstChild;
195
195
  o(t, c(V, {
196
196
  get when() {
197
197
  return e.searchable;
198
198
  },
199
199
  get fallback() {
200
200
  return (() => {
201
- var l = Ie(), n = l.firstChild;
202
- return te(l, R(Z, {
201
+ var l = Re(), n = l.firstChild;
202
+ return te(l, I(Z, {
203
203
  type: "button",
204
204
  onClick: () => y(!h())
205
205
  }), !1, !0), o(n, () => X() || e.placeholder || u.t("selectPlaceholder")), o(l, c($e, {
@@ -209,7 +209,7 @@ function U(e) {
209
209
  },
210
210
  get children() {
211
211
  var l = Se();
212
- return te(l, R(Z, {
212
+ return te(l, I(Z, {
213
213
  type: "text",
214
214
  autocomplete: "off",
215
215
  get readOnly() {
@@ -220,7 +220,7 @@ function U(e) {
220
220
  return e.placeholder ?? u.t("searchPlaceholder");
221
221
  },
222
222
  get value() {
223
- return K(() => !!h())() ? H() : X();
223
+ return z(() => !!h())() ? M() : X();
224
224
  },
225
225
  onClick: () => y(!0),
226
226
  onInput: (n) => {
@@ -234,7 +234,7 @@ function U(e) {
234
234
  var i = O;
235
235
  return typeof i == "function" ? le(i, a) : O = a, o(a, c(V, {
236
236
  get when() {
237
- return K(() => !e.multiple)() && !e.options.some((l) => l.value === "");
237
+ return z(() => !e.multiple)() && !e.options.some((l) => l.value === "");
238
238
  },
239
239
  get children() {
240
240
  var l = _e();
@@ -245,7 +245,7 @@ function U(e) {
245
245
  return e.values.filter((l) => l !== "" && !e.options.some((n) => n.value === l));
246
246
  },
247
247
  children: (l) => (() => {
248
- var n = Ke();
248
+ var n = ze();
249
249
  return n.value = l, o(n, l), n;
250
250
  })()
251
251
  }), null), o(a, c(Q, {
@@ -253,7 +253,7 @@ function U(e) {
253
253
  return e.options;
254
254
  },
255
255
  children: (l) => (() => {
256
- var n = Me();
256
+ var n = Ke();
257
257
  return o(n, () => l.label), P((v) => {
258
258
  var r = e.values.includes(l.value), f = l.disabled;
259
259
  return r !== v.e && (n.selected = v.e = r), f !== v.t && (n.disabled = v.t = f), v;
@@ -273,13 +273,14 @@ function U(e) {
273
273
  return ie();
274
274
  },
275
275
  layerRef: (l) => {
276
- I = l;
276
+ R = l;
277
277
  },
278
278
  get dir() {
279
279
  return u.direction;
280
280
  },
281
281
  get style() {
282
282
  return {
283
+ "z-index": e.zIndex,
283
284
  width: "max-content",
284
285
  "min-width": ue() + "px",
285
286
  "max-width": "calc(100vw - 24px)"
@@ -316,8 +317,8 @@ function U(e) {
316
317
  return C();
317
318
  },
318
319
  children: (r, f) => (() => {
319
- var s = He(), $ = s.firstChild;
320
- return s.$$click = () => z(r), s.$$pointermove = () => !r.disabled && E(f()), s.$$pointerdown = (d) => d.preventDefault(), o($, c(V, {
320
+ var s = Me(), $ = s.firstChild;
321
+ return s.$$click = () => j(r), s.$$pointermove = () => !r.disabled && E(f()), s.$$pointerdown = (d) => d.preventDefault(), o($, c(V, {
321
322
  get when() {
322
323
  return e.values.includes(r.value);
323
324
  },
@@ -327,7 +328,7 @@ function U(e) {
327
328
  });
328
329
  }
329
330
  })), o(s, (() => {
330
- var d = K(() => !!e.renderOption);
331
+ var d = z(() => !!e.renderOption);
331
332
  return () => d() ? e.renderOption(r) : r.label;
332
333
  })(), null), P((d) => {
333
334
  var A = S + "-" + f(), F = e.values.includes(r.value), T = r.disabled || void 0, p = e.values.includes(r.value) ? "true" : void 0, ee = re("flex min-h-[var(--floe-row-height)] items-center gap-2 rounded-sm px-2 text-[length:var(--floe-type-control)]", L() === f() && "bg-accent text-accent-foreground", r.disabled ? "opacity-50" : "cursor-pointer");
@@ -342,7 +343,7 @@ function U(e) {
342
343
  })()
343
344
  })), o(l, c(V, {
344
345
  get when() {
345
- return K(() => !C().length && !e.loading)() && !e.error;
346
+ return z(() => !C().length && !e.loading)() && !e.error;
346
347
  },
347
348
  get children() {
348
349
  var r = Te();
@@ -377,12 +378,12 @@ function U(e) {
377
378
  })();
378
379
  }
379
380
  function tt(e) {
380
- const [u, g] = M({
381
+ const [u, g] = K({
381
382
  value: () => e.value,
382
383
  defaultValue: e.defaultValue ?? "",
383
384
  onChange: (b) => e.onChange?.(b)
384
385
  });
385
- return c(U, R(e, {
386
+ return c(U, I(e, {
386
387
  get values() {
387
388
  return [u()];
388
389
  },
@@ -393,12 +394,12 @@ function tt(e) {
393
394
  }));
394
395
  }
395
396
  function lt(e) {
396
- const [u, g] = M({
397
+ const [u, g] = K({
397
398
  value: () => e.value,
398
399
  defaultValue: e.defaultValue ?? "",
399
400
  onChange: (b) => e.onChange?.(b)
400
401
  });
401
- return c(U, R(e, {
402
+ return c(U, I(e, {
402
403
  searchable: !0,
403
404
  get values() {
404
405
  return [u()];
@@ -410,12 +411,12 @@ function lt(e) {
410
411
  }));
411
412
  }
412
413
  function at(e) {
413
- const [u, g] = M({
414
+ const [u, g] = K({
414
415
  value: () => e.value,
415
416
  defaultValue: e.defaultValue ?? [],
416
417
  onChange: (b) => e.onChange?.(b)
417
418
  });
418
- return c(U, R(e, {
419
+ return c(U, I(e, {
419
420
  multiple: !0,
420
421
  get values() {
421
422
  return u();
@@ -1,3 +1,4 @@
1
+ export { PromptCard, type PromptCardProps } from './PromptCard';
1
2
  export { FeedbackIndicator, type FeedbackIndicatorProps, type FeedbackIndicatorEntry } from './FeedbackIndicator';
2
3
  export { Button, type ButtonProps, type ButtonVariant, type ButtonSize } from './Button';
3
4
  export { StableText, type StableTextProps } from './StableText';
package/dist/floe.css CHANGED
@@ -1002,3 +1002,75 @@
1002
1002
  0 0 28px color-mix(in srgb, var(--glow) 38%, transparent);
1003
1003
  }
1004
1004
  }
1005
+
1006
+ /* Contextual input uses the shared presence owner and language tokens. The
1007
+ * positioning layer never animates, and typing never schedules a motion loop. */
1008
+ .floe-prompt-card-positioner { position: fixed; pointer-events: none; width: min(24rem, var(--floe-prompt-max-width)); }
1009
+ .floe-prompt-card {
1010
+ --floe-floating-enter-duration: var(--floe-duration-base);
1011
+ --floe-floating-exit-duration: var(--floe-duration-fast);
1012
+ --floe-floating-enter-y: -0.25rem;
1013
+ --floe-floating-exit-y: -0.125rem;
1014
+ --floe-floating-enter-scale: 0.985;
1015
+ --floe-floating-exit-scale: 0.995;
1016
+ --floe-floating-origin: var(--floe-prompt-origin-x) top;
1017
+ display: flex; flex-direction: column; min-width: 0;
1018
+ max-height: var(--floe-prompt-max-height);
1019
+ overflow: hidden; pointer-events: auto;
1020
+ border: 1px solid var(--floe-line);
1021
+ border-radius: var(--floe-radius-card);
1022
+ background: var(--floe-plane-float);
1023
+ color: var(--floe-ink);
1024
+ font-size: var(--floe-type-body);
1025
+ line-height: var(--floe-line-body);
1026
+ }
1027
+ .floe-prompt-card[data-floating-side='top'] {
1028
+ --floe-floating-enter-y: 0.25rem;
1029
+ --floe-floating-exit-y: 0.125rem;
1030
+ --floe-floating-origin: var(--floe-prompt-origin-x) bottom;
1031
+ }
1032
+ .floe-prompt-card[data-floating-side='edge'] {
1033
+ --floe-floating-enter-y: 0;
1034
+ --floe-floating-exit-y: 0;
1035
+ --floe-floating-enter-scale: 1;
1036
+ --floe-floating-exit-scale: 1;
1037
+ }
1038
+ .floe-prompt-card-header {
1039
+ display: flex; align-items: center; flex-shrink: 0;
1040
+ gap: var(--floe-gap-control);
1041
+ padding: var(--floe-pad-control) var(--floe-pad-control) 0 var(--floe-pad-card);
1042
+ }
1043
+ .floe-prompt-card-header h2 {
1044
+ flex: 1; min-width: 0; margin: 0;
1045
+ font-size: var(--floe-type-supporting); line-height: var(--floe-line-control);
1046
+ font-weight: 500; color: var(--floe-ink-soft);
1047
+ }
1048
+ .floe-prompt-card-icon { display: grid; place-items: center; flex-shrink: 0; width: 1rem; height: 1rem; }
1049
+ .floe-prompt-card-icon > svg { width: 100%; height: 100%; }
1050
+ .floe-prompt-card .floe-prompt-card-close { width: var(--floe-control-height-xs); height: var(--floe-control-height-xs); border-radius: var(--floe-radius-sm); }
1051
+ .floe-prompt-card-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; padding: var(--floe-pad-tight) var(--floe-pad-card) var(--floe-pad-group); }
1052
+ .floe-prompt-card-question { margin-bottom: var(--floe-gap-control); font-size: var(--floe-type-body); line-height: var(--floe-line-body); font-weight: 500; overflow-wrap: anywhere; }
1053
+ .floe-prompt-card-field { border: 0; }
1054
+ .floe-prompt-card-input {
1055
+ display: block; width: 100%; min-height: 2.5rem; max-height: min(10rem, 30dvh);
1056
+ padding: var(--floe-pad-tight) 0; border: 0; border-radius: 0;
1057
+ background: transparent; font: inherit; line-height: 1.5;
1058
+ field-sizing: content; resize: none;
1059
+ }
1060
+ .floe-prompt-card-input::placeholder { color: var(--floe-field-placeholder); }
1061
+ .floe-prompt-card-actions { display: flex; align-items: center; gap: var(--floe-gap-control); padding: var(--floe-pad-control) 0 0; }
1062
+ .floe-prompt-card-references { min-width: 0; }
1063
+ .floe-prompt-card-tools { display: flex; align-items: center; flex: 1; min-width: 0; gap: var(--floe-gap-inline); }
1064
+ .floe-prompt-card-tools > .relative { min-width: 0; max-width: 15rem; }
1065
+ .floe-prompt-card .floe-prompt-card-attach { flex-shrink: 0; width: var(--floe-control-height-sm); height: var(--floe-control-height-sm); border-radius: var(--floe-radius-sm); }
1066
+ .floe-prompt-card .floe-prompt-card-selection { width: auto; max-width: 100%; height: var(--floe-control-height-sm); padding: 0 var(--floe-pad-control); border-color: transparent; background: transparent; font-size: var(--floe-type-supporting); box-shadow: none; }
1067
+ .floe-prompt-card .floe-prompt-card-selection:hover { background: var(--muted); }
1068
+ .floe-prompt-card .floe-prompt-card-submit { flex-shrink: 0; width: var(--floe-control-height-sm); height: var(--floe-control-height-sm); border-radius: 50%; }
1069
+ .floe-prompt-card-feedback { margin-top: var(--floe-gap-control); font-size: var(--floe-type-supporting); line-height: var(--floe-line-control); color: var(--error); }
1070
+ .floe-prompt-card-feedback > p { margin: 0; }
1071
+ @media (pointer: coarse) {
1072
+ .floe-prompt-card .floe-prompt-card-close, .floe-prompt-card .floe-prompt-card-attach, .floe-prompt-card .floe-prompt-card-submit { width: 2.75rem; height: 2.75rem; }
1073
+ .floe-prompt-card-input { font-size: 1rem; }
1074
+ .floe-prompt-card .floe-prompt-card-selection { min-height: 2.75rem; }
1075
+ }
1076
+ @media (forced-colors: active) { .floe-prompt-card { border-color: CanvasText; } }