@abuzareal/contour-ui 0.2.1 → 0.3.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 (38) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/COMPOSITION.md +193 -0
  3. package/CONTRACTS.md +24 -24
  4. package/NEXTJS.md +3 -1
  5. package/PUBLIC-API.md +174 -174
  6. package/README.md +7 -7
  7. package/dist/components/ui/Button.d.ts +10 -2
  8. package/dist/components/ui/Button.js +7 -3
  9. package/dist/components/ui/Checkbox.d.ts +7 -1
  10. package/dist/components/ui/Checkbox.js +8 -6
  11. package/dist/components/ui/DepthButton.d.ts +5 -2
  12. package/dist/components/ui/DepthButton.js +8 -3
  13. package/dist/components/ui/Dialog.d.ts +21 -3
  14. package/dist/components/ui/Dialog.js +17 -11
  15. package/dist/components/ui/ExternalLink.d.ts +3 -2
  16. package/dist/components/ui/ExternalLink.js +7 -3
  17. package/dist/components/ui/IconButton.d.ts +10 -2
  18. package/dist/components/ui/IconButton.js +7 -3
  19. package/dist/components/ui/Popover.d.ts +19 -4
  20. package/dist/components/ui/Popover.js +16 -9
  21. package/dist/components/ui/Slider.d.ts +2 -1
  22. package/dist/components/ui/Slider.js +5 -4
  23. package/dist/components/ui/Switch.d.ts +2 -1
  24. package/dist/components/ui/Switch.js +5 -4
  25. package/dist/components/ui/Tabs.d.ts +16 -4
  26. package/dist/components/ui/Tabs.js +46 -24
  27. package/dist/components/ui/ThemeToggle.d.ts +2 -1
  28. package/dist/components/ui/ThemeToggle.js +5 -3
  29. package/dist/hooks/useControlRef.js +2 -2
  30. package/dist/hooks/useTabRefs.d.ts +4 -0
  31. package/dist/hooks/useTabRefs.js +12 -0
  32. package/dist/lib/componentProps.d.ts +5 -0
  33. package/dist/lib/componentProps.js +1 -0
  34. package/dist/lib/composeEventHandlers.d.ts +4 -0
  35. package/dist/lib/composeEventHandlers.js +8 -0
  36. package/dist/lib/composeRefs.d.ts +3 -0
  37. package/dist/lib/composeRefs.js +24 -0
  38. package/package.json +3 -2
@@ -6,8 +6,8 @@ export default function useControlRef(forwarded) {
6
6
  useImperativeHandle(forwarded, () => {
7
7
  const element = ref.current;
8
8
  if (!element)
9
- throw new Error("The field control must be mounted before exposing its ref.");
9
+ throw new Error("The native target must be mounted before exposing its ref.");
10
10
  return element;
11
- });
11
+ }, []);
12
12
  return { ref, attach: ref };
13
13
  }
@@ -0,0 +1,4 @@
1
+ import { type RefObject } from "react";
2
+ import type { TabItem } from "../components/ui/Tabs.js";
3
+ /** Keep ID-based internal focus targets and caller button refs in the same lifecycle. */
4
+ export default function useTabRefs(tabs: TabItem[], targets: RefObject<Map<string, HTMLButtonElement>>): import("react").RefCallback<HTMLButtonElement>[];
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ import { useMemo } from "react";
3
+ import { composeRefs } from "../lib/composeRefs.js";
4
+ /** Keep ID-based internal focus targets and caller button refs in the same lifecycle. */
5
+ export default function useTabRefs(tabs, targets) {
6
+ return useMemo(() => tabs.map((tab) => composeRefs((element) => {
7
+ if (element)
8
+ targets.current?.set(tab.id, element);
9
+ else
10
+ targets.current?.delete(tab.id);
11
+ }, tab.buttonProps?.ref)), [tabs, targets]);
12
+ }
@@ -0,0 +1,5 @@
1
+ import type { ComponentPropsWithRef, JSX } from "react";
2
+ /** Props customize existing owned DOM parts; children and raw markup stay component-owned. */
3
+ export type NativePartProps<Tag extends keyof JSX.IntrinsicElements> = Omit<ComponentPropsWithRef<Tag>, "children" | "dangerouslySetInnerHTML"> & {
4
+ [name: `data-${string}`]: string | number | boolean | undefined;
5
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ /** Caller vetoes an internal action without replacing required state/ARIA wiring. */
2
+ export declare function composeEventHandlers<Event extends {
3
+ defaultPrevented: boolean;
4
+ }>(caller: ((event: Event) => void) | undefined, internal: (event: Event) => void): (event: Event) => void;
@@ -0,0 +1,8 @@
1
+ /** Caller vetoes an internal action without replacing required state/ARIA wiring. */
2
+ export function composeEventHandlers(caller, internal) {
3
+ return (event) => {
4
+ caller?.(event);
5
+ if (!event.defaultPrevented)
6
+ internal(event);
7
+ };
8
+ }
@@ -0,0 +1,3 @@
1
+ import type { Ref, RefCallback } from "react";
2
+ /** Retain internal nodes and caller refs, honoring React 19 cleanup callbacks on detach. */
3
+ export declare function composeRefs<Element>(...refs: (Ref<Element> | undefined)[]): RefCallback<Element>;
@@ -0,0 +1,24 @@
1
+ /** Retain internal nodes and caller refs, honoring React 19 cleanup callbacks on detach. */
2
+ export function composeRefs(...refs) {
3
+ let cleanups = [];
4
+ return (element) => {
5
+ for (const cleanup of cleanups)
6
+ cleanup();
7
+ cleanups = [];
8
+ if (element === null)
9
+ return;
10
+ for (const ref of refs) {
11
+ if (typeof ref === "function") {
12
+ const cleanup = ref(element);
13
+ cleanups.push(typeof cleanup === "function" ? () => cleanup() : () => ref(null));
14
+ }
15
+ else if (ref) {
16
+ // RefObject is read-only in React 18's consumer types; assigning is React's ref contract.
17
+ Object.assign(ref, { current: element });
18
+ cleanups.push(() => {
19
+ Object.assign(ref, { current: null });
20
+ });
21
+ }
22
+ }
23
+ };
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abuzareal/contour-ui",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "description": "Editorial React components, themes, restrained motion, and optional Three.js objects.",
6
6
  "type": "module",
@@ -15,7 +15,8 @@
15
15
  "CODE_OF_CONDUCT.md",
16
16
  "NEXTJS.md",
17
17
  "CONTRACTS.md",
18
- "PUBLIC-API.md"
18
+ "PUBLIC-API.md",
19
+ "COMPOSITION.md"
19
20
  ],
20
21
  "sideEffects": [
21
22
  "**/*.css"