@gusnips/react 0.9.11 → 0.9.13

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.
package/README.md CHANGED
@@ -417,6 +417,27 @@ In jsdom tests, mock `window.matchMedia`, which jsdom does not have, and run
417
417
  `delete window.__frontkitTheme` between tests. There is one controller per page, and a jsdom
418
418
  window lasts the whole file.
419
419
 
420
+ ## A copy button that says when it failed
421
+
422
+ ```tsx
423
+ import { useCopy } from "@gusnips/react";
424
+
425
+ const { state, copy } = useCopy();
426
+
427
+ <button onClick={() => void copy(apiKey)} aria-live="polite">
428
+ {state === "copied" ? "Copied" : state === "failed" ? "Select it and copy it yourself" : "Copy"}
429
+ </button>;
430
+ ```
431
+
432
+ Of eight copy buttons we read, five failed without a word, so the reader pasted whatever was
433
+ already on the clipboard. Two more threw on a page served without https, where there is no
434
+ clipboard API. `useCopy` shows `"copied"` for 2 seconds or `"failed"` for 6, then goes back to
435
+ `"idle"`, and a second copy restarts the clock. `copy` resolves `false` instead of throwing, so a
436
+ toast needs no `catch`. Outside a component, `copyText(text)` does the write on its own.
437
+
438
+ The words are yours, and so is the live region: a label that changes needs `aria-live` to be
439
+ heard.
440
+
420
441
  ## Also here
421
442
 
422
443
  `ErrorBoundary`, an SSE reader split into a platform-free parser and a stream wrapper,
@@ -459,6 +480,8 @@ writes you no longer own.
459
480
  The main entry works in React Native. It imports `react` and nothing else you would have to go
460
481
  find — no `react-dom`, no router, no store — so the fetch client, the retry rule and the SSE
461
482
  parser all come along, and the four things that need a browser stay behind the subpaths above.
483
+ `useCopy` imports fine there but has no `navigator.clipboard` to write to, so every copy answers
484
+ `"failed"`: use the platform's clipboard on a phone.
462
485
 
463
486
  ## The Base UI wrappers
464
487
 
package/dist/copy.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /** Write `text` to the clipboard. `false` when the browser refused or has no clipboard API. */
2
+ export declare function copyText(text: string): Promise<boolean>;
3
+ export type CopyState = "idle" | "copied" | "failed";
4
+ export interface CopyOptions {
5
+ /** How long `"copied"` shows. Default 2000 ms. */
6
+ copiedMs?: number;
7
+ /** How long `"failed"` shows. Default 6000 ms: a failure is a sentence the reader has to act on. */
8
+ failedMs?: number;
9
+ }
10
+ /**
11
+ * A copy with an outcome the reader can see. What it says stays yours — "Copied", or "Select it
12
+ * and copy it yourself", in a label or a toast — and so does announcing it: a label that changes
13
+ * needs `aria-live="polite"` to be heard.
14
+ *
15
+ * The outcome goes back to `"idle"` on its own. A "Copied" that never clears makes the second copy
16
+ * look like it did not take.
17
+ */
18
+ export declare function useCopy({ copiedMs, failedMs }?: CopyOptions): {
19
+ state: CopyState;
20
+ /** Resolves `false` instead of throwing, so a caller can toast without a `catch`. */
21
+ copy: (text: string) => Promise<boolean>;
22
+ };
23
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../src/copy.ts"],"names":[],"mappings":"AAWA,+FAA+F;AAC/F,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7D;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,EAAE,QAAe,EAAE,QAAe,EAAE,GAAE,WAAgB,GAAG;IAC/E,KAAK,EAAE,SAAS,CAAC;IACjB,qFAAqF;IACrF,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1C,CAmBA"}
package/dist/copy.js ADDED
@@ -0,0 +1,46 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ // Eight products wrote a copy button, and five of them failed silently, one under a comment
3
+ // saying it must not. Silent is worse than it looks: the reader pastes whatever was already on
4
+ // the clipboard, and for a key shown once that is pasting something else over the only copy.
5
+ // Two more called `writeText` outside a `try`, and on a page not served over https there is no
6
+ // `navigator.clipboard` at all, so the click threw a TypeError instead of rejecting.
7
+ //
8
+ // No `execCommand` fallback, and none of the eight had one: it is deprecated, the async API is
9
+ // there in every browser over https, and a copy that says it failed beats a shim that pretends.
10
+ /** Write `text` to the clipboard. `false` when the browser refused or has no clipboard API. */
11
+ export async function copyText(text) {
12
+ try {
13
+ await navigator.clipboard.writeText(text);
14
+ return true;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ /**
21
+ * A copy with an outcome the reader can see. What it says stays yours — "Copied", or "Select it
22
+ * and copy it yourself", in a label or a toast — and so does announcing it: a label that changes
23
+ * needs `aria-live="polite"` to be heard.
24
+ *
25
+ * The outcome goes back to `"idle"` on its own. A "Copied" that never clears makes the second copy
26
+ * look like it did not take.
27
+ */
28
+ export function useCopy({ copiedMs = 2000, failedMs = 6000 } = {}) {
29
+ // A new object on every copy, so copying again restarts the clock even when the state is the
30
+ // same: two copies a second apart read "Copied" for two seconds after the second one.
31
+ const [outcome, setOutcome] = useState({ state: "idle" });
32
+ useEffect(() => {
33
+ if (outcome.state === "idle")
34
+ return;
35
+ const ms = outcome.state === "copied" ? copiedMs : failedMs;
36
+ const timer = setTimeout(() => setOutcome({ state: "idle" }), ms);
37
+ return () => clearTimeout(timer);
38
+ }, [outcome, copiedMs, failedMs]);
39
+ const copy = useCallback(async (text) => {
40
+ const copied = await copyText(text);
41
+ setOutcome({ state: copied ? "copied" : "failed" });
42
+ return copied;
43
+ }, []);
44
+ return { state: outcome.state, copy };
45
+ }
46
+ //# sourceMappingURL=copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.js","sourceRoot":"","sources":["../src/copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,4FAA4F;AAC5F,+FAA+F;AAC/F,6FAA6F;AAC7F,+FAA+F;AAC/F,qFAAqF;AACrF,EAAE;AACF,+FAA+F;AAC/F,gGAAgG;AAEhG,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAWD;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,QAAQ,GAAG,IAAI,KAAkB,EAAE;IAK5E,6FAA6F;IAC7F,sFAAsF;IACtF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAuB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAEhF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM;YAAE,OAAO;QACrC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAElC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC9C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpD,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { cn } from "./cn.ts";
2
+ export { copyText, useCopy, type CopyOptions, type CopyState } from "./copy.ts";
2
3
  export { returnPathFromLocation, safeInternalPath, type PathParts } from "./internal-path.ts";
3
4
  export { ApiError, isAbortError, retryAfterSecs } from "./api-error.ts";
4
5
  export { createApiClient, type ApiClient, type ApiClientOptions, type RefreshResult, type RequestOptions, type SessionAdapter, } from "./api-client.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,eAAe,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EACZ,WAAW,EACX,KAAK,oBAAoB,EACzB,KAAK,SAAS,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAElF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,eAAe,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EACZ,WAAW,EACX,KAAK,oBAAoB,EACzB,KAAK,SAAS,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,EACb,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAElF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@
30
30
  // Check that claim against `dist/`, never against this file: a type-only re-export looks
31
31
  // identical in source.
32
32
  export { cn } from "./cn.js";
33
+ export { copyText, useCopy } from "./copy.js";
33
34
  export { returnPathFromLocation, safeInternalPath } from "./internal-path.js";
34
35
  export { ApiError, isAbortError, retryAfterSecs } from "./api-error.js";
35
36
  export { createApiClient, } from "./api-client.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,2CAA2C;AAC3C,EAAE;AACF,+FAA+F;AAC/F,gGAAgG;AAChG,+FAA+F;AAC/F,iGAAiG;AACjG,0BAA0B;AAC1B,EAAE;AACF,qEAAqE;AACrE,8DAA8D;AAC9D,uEAAuE;AACvE,gEAAgE;AAChE,4EAA4E;AAC5E,4FAA4F;AAC5F,8FAA8F;AAC9F,EAAE;AACF,2FAA2F;AAC3F,iGAAiG;AACjG,+FAA+F;AAC/F,gGAAgG;AAChG,4EAA4E;AAC5E,EAAE;AACF,2FAA2F;AAC3F,iGAAiG;AACjG,qFAAqF;AACrF,6FAA6F;AAC7F,iGAAiG;AACjG,yFAAyF;AACzF,uBAAuB;AAEvB,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAkB,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,eAAe,GAMhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAC;AAEzE,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EACZ,WAAW,GAGZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,GAGd,MAAM,qBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,YAAY,GAQb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,iGAAiG;AACjG,kGAAkG;AAClG,6FAA6F;AAC7F,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAwB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,2CAA2C;AAC3C,EAAE;AACF,+FAA+F;AAC/F,gGAAgG;AAChG,+FAA+F;AAC/F,iGAAiG;AACjG,0BAA0B;AAC1B,EAAE;AACF,qEAAqE;AACrE,8DAA8D;AAC9D,uEAAuE;AACvE,gEAAgE;AAChE,4EAA4E;AAC5E,4FAA4F;AAC5F,8FAA8F;AAC9F,EAAE;AACF,2FAA2F;AAC3F,iGAAiG;AACjG,+FAA+F;AAC/F,gGAAgG;AAChG,4EAA4E;AAC5E,EAAE;AACF,2FAA2F;AAC3F,iGAAiG;AACjG,qFAAqF;AACrF,6FAA6F;AAC7F,iGAAiG;AACjG,yFAAyF;AACzF,uBAAuB;AAEvB,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAoC,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAkB,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,eAAe,GAMhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAC;AAEzE,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EACZ,WAAW,GAGZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,aAAa,GAGd,MAAM,qBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,YAAY,GAQb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,sBAAsB,CAAC;AAE9B,iGAAiG;AACjG,kGAAkG;AAClG,6FAA6F;AAC7F,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAwB,MAAM,WAAW,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/ui/combobox.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/ui/combobox.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtE,eAAO,MAAM,YAAY,uBAAiB,CAAC;AAC3C,eAAO,MAAM,aAAa,2JAAkB,CAAC;AAC7C,eAAO,MAAM,kBAAkB,0JAAuB,CAAC;AACvD,eAAO,MAAM,eAAe,0JAAoB,CAAC;AACjD,eAAO,MAAM,aAAa,4JAAkB,CAAC;AAC7C,eAAO,MAAM,cAAc,0JAAmB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,8JAAuB,CAAC;AACvD,eAAO,MAAM,aAAa,yJAAkB,CAAC;AAC7C,eAAO,MAAM,YAAY,wJAAiB,CAAC;AAC3C,eAAO,MAAM,YAAY,+IAAiB,CAAC;AAC3C,eAAO,MAAM,aAAa,yJAAkB,CAAC;AAC7C,eAAO,MAAM,aAAa,yJAAkB,CAAC;AAC7C,eAAO,MAAM,kBAAkB,8JAAuB,CAAC;AAEvD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,CAAC,GAAG,IAAI,EACf,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAC5B,MAAM,CAGR;AAED,yFAAyF;AACzF,KAAK,oBAAoB,GACvB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,OAAO,CAAC,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAElG,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,IAAI,CACjC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAC/B,UAAU,GACV,OAAO,GACP,eAAe,GACf,QAAQ,GACR,OAAO,GACP,cAAc,GACd,UAAU,GACV,MAAM,GACN,aAAa,GACb,YAAY,GACZ,mBAAmB,GACnB,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,CACvB,GAAG;IACF,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;IACxC,iFAAiF;IACjF,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IACpC;;;OAGG;IACH,SAAS,EAAE,SAAS,CAAC;IACrB,sFAAsF;IACtF,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,oCAAoC;IACpC,SAAS,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,cAAc,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,UAAU,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC;IACnC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;CAC9C,GAAG,oBAAoB,CAAC;AAEzB;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAC1B,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,KAAK,EACL,WAAW,EACX,SAAS,EACT,cAAc,EACd,UAAU,EACV,eAAe,EACf,YAAY,EACZ,GAAG,IAAI,EACR,EAAE,aAAa,CAAC,CAAC,CAAC,+BAyHlB"}
@@ -65,6 +65,6 @@ export function Combobox({ value, search, getKey, getLabel, renderItem, emptyHin
65
65
  ],
66
66
  // The caller's classes land BEFORE the space reserved for the buttons is
67
67
  // re-applied below, so a `px-*` of their own cannot swallow it.
68
- className) }), _jsxs("span", { className: "absolute top-1/2 right-1.5 z-10 flex -translate-y-1/2 items-center gap-0.5", children: [_jsx(Primitive.Clear, { "aria-label": clearLabel, className: "inline-flex rounded-full p-1.5 text-muted-foreground", children: _jsx(CloseGlyph, {}) }), _jsx(Primitive.Trigger, { "aria-label": openLabel, className: "inline-flex rounded-full p-1.5 text-muted-foreground", children: _jsx(ChevronGlyph, {}) })] })] }), _jsx(Primitive.Portal, { children: _jsx(Primitive.Positioner, { sideOffset: 4, ...positionerProps, className: mergeClassName("z-[60] max-w-[var(--available-width)] outline-none", positionerProps?.className), children: _jsxs(Primitive.Popup, { className: mergeClassName("w-[var(--anchor-width)] overflow-hidden border border-border bg-popover text-popover-foreground outline-none transition-[scale,opacity] data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0", popupClassName), children: [_jsx(Primitive.Empty, { children: _jsx("div", { className: "px-3 py-2 text-muted-foreground", children: loading ? loadingHint : emptyHint }) }), _jsx(Primitive.List, { className: "max-h-[var(--available-height)] overflow-y-auto", children: (item) => (_jsx(Primitive.Item, { value: item, className: "cursor-default px-3 py-2 outline-none data-highlighted:bg-accent data-highlighted:text-accent-foreground", children: renderItem ? renderItem(item) : getLabel(item) }, getKey(item))) })] }) }) })] }));
68
+ className) }), _jsxs("span", { className: "absolute top-1/2 right-1.5 z-10 flex -translate-y-1/2 items-center gap-0.5", children: [_jsx(Primitive.Clear, { "aria-label": clearLabel, className: "inline-flex rounded-full p-1.5 text-muted-foreground", children: _jsx(CloseGlyph, {}) }), _jsx(Primitive.Trigger, { "aria-label": openLabel, className: "inline-flex rounded-full p-1.5 text-muted-foreground", children: _jsx(ChevronGlyph, {}) })] })] }), _jsx(Primitive.Portal, { children: _jsx(Primitive.Positioner, { sideOffset: 4, ...positionerProps, className: mergeClassName("z-[60] max-w-[var(--available-width)] outline-none", positionerProps?.className), children: _jsxs(Primitive.Popup, { className: mergeClassName("w-[var(--anchor-width)] overflow-hidden border border-border bg-popover text-popover-foreground outline-none transition-[scale,opacity] data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0", popupClassName), children: [_jsx(Primitive.Empty, { children: _jsx("div", { className: "px-3 py-2 text-muted-foreground", children: loading ? loadingHint : emptyHint }) }), _jsx(Primitive.List, { className: "max-h-[var(--available-height)] overflow-y-auto", children: (item) => (_jsx(Primitive.Item, { value: item, className: "cursor-default px-3 py-2 data-highlighted:bg-accent data-highlighted:text-accent-foreground forced-colors:data-highlighted:outline-2 forced-colors:data-highlighted:-outline-offset-2", children: renderItem ? renderItem(item) : getLabel(item) }, getKey(item))) })] }) }) })] }));
69
69
  }
70
70
  //# sourceMappingURL=combobox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.js","sourceRoot":"","sources":["../../src/ui/combobox.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combobox.js","sourceRoot":"","sources":["../../src/ui/combobox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,IAAI,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAc,CAAC;AAExD,2FAA2F;AAC3F,8BAA8B;AAC9B,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC,UAAU,CAAC;AACvD,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAC;AACjD,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC,UAAU,CAAC;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC,UAAU,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAa,EACb,KAAa,EACb,KAAe,EACf,QAA6B;IAE7B,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IACvB,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC/C,CAAC;AA6DD;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAI,EAC1B,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,KAAK,EACL,WAAW,EACX,SAAS,EACT,cAAc,EACd,UAAU,EACV,eAAe,EACf,YAAY,EACZ,GAAG,IAAI,EACU;IACjB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5D,OAAO,CACL,MAAC,SAAS,CAAC,IAAI,IACb,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,iBAAiB,EAAE,QAAQ,EAC3B,kBAAkB,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC;QACnE,wFAAwF;QACxF,qFAAqF;QACrF,mFAAmF;QACnF,0BAA0B;QAC1B,MAAM,EAAE,IAAI,EACZ,UAAU,EAAE,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAC5D,kBAAkB,EAAE,CAAC,IAAI,EAAE,EAAE;YAC3B,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,IAAI,CAAC,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC,EACD,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,kFAAkF;YAClF,IAAI,IAAI;gBAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACvB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC,KACG,IAAI,aAER,MAAC,SAAS,CAAC,UAAU,IAAC,SAAS,EAAC,UAAU,aACvC,WAAW,CAAC,CAAC,CAAC,CACb,eAAM,SAAS,EAAC,yFAAyF,YACtG,WAAW,GACP,CACR,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,SAAS,CAAC,KAAK,kBACF,KAAK,EACjB,YAAY,EAAC,KAAK,KACd,UAAU,EACd,SAAS,EAAE,cAAc,CACvB;4BACE,mFAAmF;4BACnF,oFAAoF;4BACpF,qMAAqM;4BACrM,WAAW,IAAI,MAAM;yBACtB;wBACD,yEAAyE;wBACzE,gEAAgE;wBAChE,SAAS,CACV,GACD,EACF,gBAAM,SAAS,EAAC,4EAA4E,aAI1F,KAAC,SAAS,CAAC,KAAK,kBACF,UAAU,EACtB,SAAS,EAAC,sDAAsD,YAEhE,KAAC,UAAU,KAAG,GACE,EAClB,KAAC,SAAS,CAAC,OAAO,kBACJ,SAAS,EACrB,SAAS,EAAC,sDAAsD,YAEhE,KAAC,YAAY,KAAG,GACE,IACf,IACc,EACvB,KAAC,SAAS,CAAC,MAAM,cAIf,KAAC,SAAS,CAAC,UAAU,IACnB,UAAU,EAAE,CAAC,KACT,eAAe,EACnB,SAAS,EAAE,cAAc,CACvB,oDAAoD,EACpD,eAAe,EAAE,SAAS,CAC3B,YAED,MAAC,SAAS,CAAC,KAAK,IACd,SAAS,EAAE,cAAc,CACvB,2PAA2P,EAC3P,cAAc,CACf,aAOD,KAAC,SAAS,CAAC,KAAK,cACd,cAAK,SAAS,EAAC,iCAAiC,YAC7C,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,GAC9B,GACU,EAQlB,KAAC,SAAS,CAAC,IAAI,IAAC,SAAS,EAAC,iDAAiD,YACxE,CAAC,IAAO,EAAE,EAAE,CAAC,CACZ,KAAC,SAAS,CAAC,IAAI,IAEb,KAAK,EAAE,IAAI,EACX,SAAS,EAAC,uLAAuL,YAEhM,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAJ1C,MAAM,CAAC,IAAI,CAAC,CAKF,CAClB,GACc,IACD,GACG,GACN,IACJ,CAClB,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/ui/select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtE,eAAO,MAAM,UAAU,uBAAiB,CAAC;AACzC,eAAO,MAAM,aAAa,wJAAoB,CAAC;AAC/C,eAAO,MAAM,WAAW,oJAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,mJAAiB,CAAC;AACzC,eAAO,MAAM,YAAY,oJAAmB,CAAC;AAC7C,eAAO,MAAM,gBAAgB,wJAAuB,CAAC;AACrD,eAAO,MAAM,WAAW,mJAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,kJAAiB,CAAC;AACzC,eAAO,MAAM,UAAU,0IAAiB,CAAC;AACzC,eAAO,MAAM,mBAAmB,4JAA0B,CAAC;AAC3D,eAAO,MAAM,cAAc,iJAAqB,CAAC;AACjD,eAAO,MAAM,WAAW,mJAAkB,CAAC;AAC3C,eAAO,MAAM,gBAAgB,wJAAuB,CAAC;AACrD,eAAO,MAAM,eAAe,0IAAsB,CAAC;AAEnD,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CACvD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAC9B,UAAU,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,CACnD,GAAG;IACF,OAAO,CAAC,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACrC,gFAAgF;IAChF,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,YAAY,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC;IACvC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;CAC9C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAChD,KAAK,EACL,OAAY,EACZ,WAAW,EACX,UAAU,EACV,UAAU,EACV,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,cAAc,EACd,YAAY,EACZ,eAAe,EACf,GAAG,IAAI,EACR,EAAE,WAAW,CAAC,CAAC,CAAC,+BAmGhB"}
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/ui/select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtE,eAAO,MAAM,UAAU,uBAAiB,CAAC;AACzC,eAAO,MAAM,aAAa,wJAAoB,CAAC;AAC/C,eAAO,MAAM,WAAW,oJAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,mJAAiB,CAAC;AACzC,eAAO,MAAM,YAAY,oJAAmB,CAAC;AAC7C,eAAO,MAAM,gBAAgB,wJAAuB,CAAC;AACrD,eAAO,MAAM,WAAW,mJAAkB,CAAC;AAC3C,eAAO,MAAM,UAAU,kJAAiB,CAAC;AACzC,eAAO,MAAM,UAAU,0IAAiB,CAAC;AACzC,eAAO,MAAM,mBAAmB,4JAA0B,CAAC;AAC3D,eAAO,MAAM,cAAc,iJAAqB,CAAC;AACjD,eAAO,MAAM,WAAW,mJAAkB,CAAC;AAC3C,eAAO,MAAM,gBAAgB,wJAAuB,CAAC;AACrD,eAAO,MAAM,eAAe,0IAAsB,CAAC;AAEnD,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CACvD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAC9B,UAAU,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,CACnD,GAAG;IACF,OAAO,CAAC,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACrC,gFAAgF;IAChF,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpD,cAAc,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,YAAY,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC;IACvC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;CAC9C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAChD,KAAK,EACL,OAAY,EACZ,WAAW,EACX,UAAU,EACV,UAAU,EACV,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,cAAc,EACd,YAAY,EACZ,eAAe,EACf,GAAG,IAAI,EACR,EAAE,WAAW,CAAC,CAAC,CAAC,+BAwGhB"}
package/dist/ui/select.js CHANGED
@@ -43,6 +43,6 @@ export function Select({ value, options = [], placeholder, emptyLabel, clearLabe
43
43
  // An Item with `value={null}`, not a button above the list: only an item is
44
44
  // reachable by arrow keys and typeahead, and only an item closes the popup
45
45
  // on its own. `null` is what arrives at `onValueChange`.
46
- _jsxs(Primitive.Item, { value: null, className: "flex cursor-default items-center gap-2 px-3 py-2 text-muted-foreground outline-none data-highlighted:bg-accent data-highlighted:text-accent-foreground", children: [_jsx("span", { className: "size-4 shrink-0", "aria-hidden": "true" }), _jsx(Primitive.ItemText, { children: clearLabel })] })) : null, options.length === 0 ? (_jsx("div", { className: "px-3 py-2 text-muted-foreground", children: emptyLabel })) : (options.map((option) => (_jsxs(Primitive.Item, { value: option.value, disabled: option.disabled, className: "flex cursor-default items-center gap-2 px-3 py-2 outline-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground", children: [_jsx("span", { className: "size-4 shrink-0", children: _jsx(Primitive.ItemIndicator, { children: indicator ?? _jsx(CheckGlyph, {}) }) }), option.icon ? (_jsx("span", { className: "inline-flex shrink-0", children: option.icon })) : null, _jsx(Primitive.ItemText, { children: option.label })] }, option.value))))] }) }) }) })] }));
46
+ _jsxs(Primitive.Item, { value: null, className: "flex cursor-default items-center gap-2 px-3 py-2 text-muted-foreground focus-visible:outline-hidden focus-visible:-outline-offset-2 data-highlighted:bg-accent data-highlighted:text-accent-foreground", children: [_jsx("span", { className: "size-4 shrink-0", "aria-hidden": "true" }), _jsx(Primitive.ItemText, { children: clearLabel })] })) : null, options.length === 0 ? (_jsx("div", { className: "px-3 py-2 text-muted-foreground", children: emptyLabel })) : (options.map((option) => (_jsxs(Primitive.Item, { value: option.value, disabled: option.disabled, className: "flex cursor-default items-center gap-2 px-3 py-2 focus-visible:outline-hidden focus-visible:-outline-offset-2 data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground", children: [_jsx("span", { className: "size-4 shrink-0", children: _jsx(Primitive.ItemIndicator, { children: indicator ?? _jsx(CheckGlyph, {}) }) }), option.icon ? (_jsx("span", { className: "inline-flex shrink-0", children: option.icon })) : null, _jsx(Primitive.ItemText, { children: option.label })] }, option.value))))] }) }) }) })] }));
47
47
  }
48
48
  //# sourceMappingURL=select.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/ui/select.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/ui/select.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gusnips/react",
3
- "version": "0.9.11",
3
+ "version": "0.9.13",
4
4
  "description": "The headless runtime under a Vite + React SPA: typed fetch client with single-flight refresh, auth store, query defaults, route guards, error boundary, stale-tab recovery, i18n bootstrap.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -80,7 +80,7 @@
80
80
  "release:major": "bun pm version major && bun publish --access public"
81
81
  },
82
82
  "dependencies": {
83
- "@gusnips/http": "0.1.0",
83
+ "@gusnips/http": "0.1.1",
84
84
  "clsx": "^2.1.1",
85
85
  "tailwind-merge": "^3.6.0"
86
86
  },
@@ -0,0 +1,29 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { copyText } from "./copy.ts";
3
+
4
+ afterEach(() => {
5
+ vi.unstubAllGlobals();
6
+ });
7
+
8
+ describe("copyText", () => {
9
+ it("answers true once the clipboard has the text", async () => {
10
+ const writeText = vi.fn(() => Promise.resolve());
11
+ vi.stubGlobal("navigator", { clipboard: { writeText } });
12
+ await expect(copyText("sk_live_1")).resolves.toBe(true);
13
+ expect(writeText).toHaveBeenCalledWith("sk_live_1");
14
+ });
15
+
16
+ it("answers false when the browser refuses the write", async () => {
17
+ vi.stubGlobal("navigator", {
18
+ clipboard: { writeText: () => Promise.reject(new DOMException("denied", "NotAllowedError")) },
19
+ });
20
+ await expect(copyText("sk_live_1")).resolves.toBe(false);
21
+ });
22
+
23
+ // Over plain http there is no `navigator.clipboard`, so `writeText` is read off `undefined` and
24
+ // throws before any promise exists. Two copies in the fleet let that escape the click handler.
25
+ it("answers false, and does not throw, where there is no clipboard API", async () => {
26
+ vi.stubGlobal("navigator", {});
27
+ await expect(copyText("sk_live_1")).resolves.toBe(false);
28
+ });
29
+ });
package/src/copy.ts ADDED
@@ -0,0 +1,62 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+
3
+ // Eight products wrote a copy button, and five of them failed silently, one under a comment
4
+ // saying it must not. Silent is worse than it looks: the reader pastes whatever was already on
5
+ // the clipboard, and for a key shown once that is pasting something else over the only copy.
6
+ // Two more called `writeText` outside a `try`, and on a page not served over https there is no
7
+ // `navigator.clipboard` at all, so the click threw a TypeError instead of rejecting.
8
+ //
9
+ // No `execCommand` fallback, and none of the eight had one: it is deprecated, the async API is
10
+ // there in every browser over https, and a copy that says it failed beats a shim that pretends.
11
+
12
+ /** Write `text` to the clipboard. `false` when the browser refused or has no clipboard API. */
13
+ export async function copyText(text: string): Promise<boolean> {
14
+ try {
15
+ await navigator.clipboard.writeText(text);
16
+ return true;
17
+ } catch {
18
+ return false;
19
+ }
20
+ }
21
+
22
+ export type CopyState = "idle" | "copied" | "failed";
23
+
24
+ export interface CopyOptions {
25
+ /** How long `"copied"` shows. Default 2000 ms. */
26
+ copiedMs?: number;
27
+ /** How long `"failed"` shows. Default 6000 ms: a failure is a sentence the reader has to act on. */
28
+ failedMs?: number;
29
+ }
30
+
31
+ /**
32
+ * A copy with an outcome the reader can see. What it says stays yours — "Copied", or "Select it
33
+ * and copy it yourself", in a label or a toast — and so does announcing it: a label that changes
34
+ * needs `aria-live="polite"` to be heard.
35
+ *
36
+ * The outcome goes back to `"idle"` on its own. A "Copied" that never clears makes the second copy
37
+ * look like it did not take.
38
+ */
39
+ export function useCopy({ copiedMs = 2000, failedMs = 6000 }: CopyOptions = {}): {
40
+ state: CopyState;
41
+ /** Resolves `false` instead of throwing, so a caller can toast without a `catch`. */
42
+ copy: (text: string) => Promise<boolean>;
43
+ } {
44
+ // A new object on every copy, so copying again restarts the clock even when the state is the
45
+ // same: two copies a second apart read "Copied" for two seconds after the second one.
46
+ const [outcome, setOutcome] = useState<{ state: CopyState }>({ state: "idle" });
47
+
48
+ useEffect(() => {
49
+ if (outcome.state === "idle") return;
50
+ const ms = outcome.state === "copied" ? copiedMs : failedMs;
51
+ const timer = setTimeout(() => setOutcome({ state: "idle" }), ms);
52
+ return () => clearTimeout(timer);
53
+ }, [outcome, copiedMs, failedMs]);
54
+
55
+ const copy = useCallback(async (text: string) => {
56
+ const copied = await copyText(text);
57
+ setOutcome({ state: copied ? "copied" : "failed" });
58
+ return copied;
59
+ }, []);
60
+
61
+ return { state: outcome.state, copy };
62
+ }
package/src/index.ts CHANGED
@@ -31,6 +31,7 @@
31
31
  // identical in source.
32
32
 
33
33
  export { cn } from "./cn.ts";
34
+ export { copyText, useCopy, type CopyOptions, type CopyState } from "./copy.ts";
34
35
  export { returnPathFromLocation, safeInternalPath, type PathParts } from "./internal-path.ts";
35
36
 
36
37
  export { ApiError, isAbortError, retryAfterSecs } from "./api-error.ts";
@@ -222,13 +222,17 @@ export function Combobox<T>({
222
222
  </Primitive.Empty>
223
223
  {/* `--available-height` is the room the positioner measured between the anchor
224
224
  and the edge of the viewport. Without it the list is unbounded and a long
225
- result set runs off the bottom of the screen with no way to reach the end. */}
225
+ result set runs off the bottom of the screen with no way to reach the end.
226
+ Focus stays in the input and the highlight follows the arrow keys, so an item
227
+ never matches `:focus-visible`. Forced colors paint no background, which takes
228
+ the highlight with it, so there the highlighted item draws an outline, inset
229
+ or the list's overflow clips it at both edges. */}
226
230
  <Primitive.List className="max-h-[var(--available-height)] overflow-y-auto">
227
231
  {(item: T) => (
228
232
  <Primitive.Item
229
233
  key={getKey(item)}
230
234
  value={item}
231
- className="cursor-default px-3 py-2 outline-none data-highlighted:bg-accent data-highlighted:text-accent-foreground"
235
+ className="cursor-default px-3 py-2 data-highlighted:bg-accent data-highlighted:text-accent-foreground forced-colors:data-highlighted:outline-2 forced-colors:data-highlighted:-outline-offset-2"
232
236
  >
233
237
  {renderItem ? renderItem(item) : getLabel(item)}
234
238
  </Primitive.Item>
@@ -27,15 +27,18 @@ const sources = readdirSync(here)
27
27
  * guard that fails on its own explanation teaches people to delete the explanation.
28
28
  */
29
29
  function linesMatching(text: string, pattern: RegExp): number[] {
30
+ return codeLines(text)
31
+ .map((line, i) => (pattern.test(line) ? i + 1 : 0))
32
+ .filter(Boolean);
33
+ }
34
+
35
+ function codeLines(text: string): string[] {
30
36
  // Block comments are BLANKED, not deleted: removing them would collapse lines and every number
31
37
  // reported after one would point at the wrong place. (That is also why this cannot share
32
38
  // `menu.test.ts`'s `codeOf`, which strips outright because it only ever counts occurrences.)
33
39
  // Blanking also means a wrapped comment line is ignored whether or not it opens with a `*`.
34
40
  const code = text.replace(/\/\*[\s\S]*?\*\//g, (block) => block.replace(/[^\n]/g, " "));
35
- return code
36
- .split("\n")
37
- .map((line, i) => (!line.trim().startsWith("//") && pattern.test(line) ? i + 1 : 0))
38
- .filter(Boolean);
41
+ return code.split("\n").map((line) => (line.trim().startsWith("//") ? "" : line));
39
42
  }
40
43
 
41
44
  describe("the wrappers do not draw their own focus ring", () => {
@@ -49,21 +52,21 @@ describe("the wrappers do not draw their own focus ring", () => {
49
52
  });
50
53
 
51
54
  // The other half: `outline-none` is legitimate on a container that takes focus
52
- // programmatically (a Popup, its Positioner, a highlighted Item), and nowhere else. It is
53
- // only a bug when it removes the outline without the primitive putting focus somewhere that
54
- // still shows one — which is what the rule above now makes impossible, since there is no
55
- // replacement ring left to write. This asserts the reset stayed inside the popup parts.
56
- it.each(sources)("$name resets the outline only on popup parts", ({ text }) => {
55
+ // programmatically (a Popup, its Positioner, a Backdrop), and nowhere else. An ITEM is not one
56
+ // of those, even though its highlight shows focus: forced colors paint no background, so the
57
+ // highlight is gone there and a bare `outline-none` leaves the item with nothing at all. An item
58
+ // hides the outline with `outline-hidden`, which Tailwind brings back in forced colors.
59
+ it.each(sources)("$name resets the outline only on popup containers", ({ text }) => {
60
+ const containers = new Set(["Popup", "Positioner", "Backdrop", "Viewport"]);
61
+ const code = codeLines(text);
57
62
  const offenders = linesMatching(text, /outline-none/).filter((line) => {
58
- // ponytail: "the nearest Primitive tag above" approximated as a 12-line lookback, which
59
- // clears every part in this folder today with room to spare. The ceiling is a part whose
60
- // props run longer than that, which would read as a violation while being correct. If that
61
- // happens, parse the enclosing JSX element instead of counting lines — do not just raise 12.
62
- const context = text
63
- .split("\n")
64
- .slice(Math.max(0, line - 12), line)
65
- .join("\n");
66
- return !/<Primitive\.(Popup|Positioner|Item|ItemsEmpty|Backdrop|Viewport)\b/.test(context);
63
+ // ponytail: the element is taken to be the nearest `<Primitive.X` at or above the line,
64
+ // since a class string sits in its element's own props. The ceiling is a plain element
65
+ // nested inside a popup part, which would read as that part; none exists today. If one
66
+ // does, parse the enclosing JSX element instead.
67
+ const above = code.slice(0, line).join("\n");
68
+ const part = [...above.matchAll(/<Primitive\.(\w+)/g)].at(-1)?.[1];
69
+ return part === undefined || !containers.has(part);
67
70
  });
68
71
  expect(offenders).toEqual([]);
69
72
  });
package/src/ui/select.tsx CHANGED
@@ -145,6 +145,11 @@ export function Select<T extends string = string>({
145
145
  popupClassName,
146
146
  )}
147
147
  >
148
+ {/* An item takes real focus as the arrow keys move, and its highlight is what shows
149
+ it, so the items hide the app's outline. `outline-hidden`, not `outline-none`:
150
+ forced colors paint no background, so the highlight is gone there, and
151
+ `outline-hidden` is the one that comes back as an outline. Inset, or the list's
152
+ overflow clips it at both edges. */}
148
153
  <Primitive.List className="max-h-[var(--available-height)] overflow-y-auto">
149
154
  {clearLabel !== undefined && value != null ? (
150
155
  // An Item with `value={null}`, not a button above the list: only an item is
@@ -152,7 +157,7 @@ export function Select<T extends string = string>({
152
157
  // on its own. `null` is what arrives at `onValueChange`.
153
158
  <Primitive.Item
154
159
  value={null}
155
- className="flex cursor-default items-center gap-2 px-3 py-2 text-muted-foreground outline-none data-highlighted:bg-accent data-highlighted:text-accent-foreground"
160
+ className="flex cursor-default items-center gap-2 px-3 py-2 text-muted-foreground focus-visible:outline-hidden focus-visible:-outline-offset-2 data-highlighted:bg-accent data-highlighted:text-accent-foreground"
156
161
  >
157
162
  <span className="size-4 shrink-0" aria-hidden="true" />
158
163
  <Primitive.ItemText>{clearLabel}</Primitive.ItemText>
@@ -166,7 +171,7 @@ export function Select<T extends string = string>({
166
171
  key={option.value}
167
172
  value={option.value}
168
173
  disabled={option.disabled}
169
- className="flex cursor-default items-center gap-2 px-3 py-2 outline-none data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground"
174
+ className="flex cursor-default items-center gap-2 px-3 py-2 focus-visible:outline-hidden focus-visible:-outline-offset-2 data-disabled:pointer-events-none data-disabled:opacity-50 data-highlighted:bg-accent data-highlighted:text-accent-foreground"
170
175
  >
171
176
  {/* The mark keeps a column of its own whether or not it is showing, so
172
177
  the labels do not shift by 16px when the selection moves. */}