@refraction-ui/react 0.12.2 → 0.13.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 (44) hide show
  1. package/dist/{applicationinsights-web-62HUCH3W.js → applicationinsights-web-H7OBLIVJ.js} +199 -68
  2. package/dist/applicationinsights-web-H7OBLIVJ.js.map +1 -0
  3. package/dist/index.cjs +900 -83
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +5 -0
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.js +692 -17
  8. package/dist/index.js.map +1 -1
  9. package/dist/internal/button/index.d.cts +12 -3
  10. package/dist/internal/button/index.d.ts +12 -3
  11. package/dist/internal/empty-state/index.d.cts +39 -0
  12. package/dist/internal/empty-state/index.d.ts +39 -0
  13. package/dist/internal/input/index.d.cts +19 -1
  14. package/dist/internal/input/index.d.ts +19 -1
  15. package/dist/internal/react-empty-state/index.d.cts +36 -0
  16. package/dist/internal/react-empty-state/index.d.ts +36 -0
  17. package/dist/internal/react-input/index.d.cts +16 -0
  18. package/dist/internal/react-input/index.d.ts +16 -0
  19. package/dist/internal/react-password-input/index.d.cts +26 -0
  20. package/dist/internal/react-password-input/index.d.ts +26 -0
  21. package/dist/internal/react-segmented-control/index.d.cts +38 -0
  22. package/dist/internal/react-segmented-control/index.d.ts +38 -0
  23. package/dist/internal/react-separator/index.d.cts +29 -0
  24. package/dist/internal/react-separator/index.d.ts +29 -0
  25. package/dist/internal/react-social-auth-button/index.d.cts +31 -0
  26. package/dist/internal/react-social-auth-button/index.d.ts +31 -0
  27. package/dist/internal/react-status-indicator/index.d.cts +5 -18
  28. package/dist/internal/react-status-indicator/index.d.ts +5 -18
  29. package/dist/internal/react-theme/index.d.cts +19 -1
  30. package/dist/internal/react-theme/index.d.ts +19 -1
  31. package/dist/internal/segmented-control/index.d.cts +56 -0
  32. package/dist/internal/segmented-control/index.d.ts +56 -0
  33. package/dist/internal/separator/index.d.cts +55 -0
  34. package/dist/internal/separator/index.d.ts +55 -0
  35. package/dist/internal/social-auth-button/index.d.cts +47 -0
  36. package/dist/internal/social-auth-button/index.d.ts +47 -0
  37. package/dist/internal/theme/index.d.cts +35 -1
  38. package/dist/internal/theme/index.d.ts +35 -1
  39. package/dist/theme.cjs +27 -4
  40. package/dist/theme.cjs.map +1 -1
  41. package/dist/theme.js +27 -4
  42. package/dist/theme.js.map +1 -1
  43. package/package.json +25 -20
  44. package/dist/applicationinsights-web-62HUCH3W.js.map +0 -1
@@ -1,32 +1,19 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
1
2
  import * as React from 'react';
2
3
  import { StatusType } from '../status-indicator/index.cjs';
3
4
  export { StatusProps as CoreStatusProps, STATUS_COLORS, STATUS_LABELS, StatusAPI, StatusType, statusContainerStyles, statusDotVariants, statusLabelStyles, statusPulseVariants } from '../status-indicator/index.cjs';
4
5
 
5
6
  interface StatusIndicatorProps {
6
7
  type: StatusType;
8
+ /** Explicit text label. Takes precedence over `children`. */
7
9
  label?: string;
10
+ /** Composable label content. Used when `label` is omitted. */
11
+ children?: React.ReactNode;
8
12
  pulse?: boolean;
9
13
  showLabel?: boolean;
10
14
  className?: string;
11
15
  }
12
- declare function StatusIndicator({ type, label, pulse, showLabel, className, }: StatusIndicatorProps): React.DetailedReactHTMLElement<{
13
- className: string;
14
- role?: string | undefined;
15
- tabIndex?: number | undefined;
16
- 'aria-label'?: string | undefined;
17
- 'aria-labelledby'?: string | undefined;
18
- 'aria-describedby'?: string | undefined;
19
- 'aria-controls'?: string | undefined;
20
- 'aria-expanded'?: boolean | undefined;
21
- 'aria-selected'?: boolean | undefined;
22
- 'aria-hidden'?: boolean | undefined;
23
- 'aria-disabled'?: boolean | undefined;
24
- 'aria-pressed'?: boolean | "mixed" | undefined;
25
- 'aria-checked'?: boolean | "mixed" | undefined;
26
- 'aria-current'?: boolean | "page" | "step" | "location" | "date" | "time" | undefined;
27
- 'aria-live'?: "off" | "assertive" | "polite" | undefined;
28
- 'aria-atomic'?: boolean | undefined;
29
- }, HTMLElement>;
16
+ declare function StatusIndicator({ type, label, children, pulse, showLabel, className, }: StatusIndicatorProps): react_jsx_runtime.JSX.Element;
30
17
  declare namespace StatusIndicator {
31
18
  var displayName: string;
32
19
  }
@@ -1,32 +1,19 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
1
2
  import * as React from 'react';
2
3
  import { StatusType } from '../status-indicator/index.js';
3
4
  export { StatusProps as CoreStatusProps, STATUS_COLORS, STATUS_LABELS, StatusAPI, StatusType, statusContainerStyles, statusDotVariants, statusLabelStyles, statusPulseVariants } from '../status-indicator/index.js';
4
5
 
5
6
  interface StatusIndicatorProps {
6
7
  type: StatusType;
8
+ /** Explicit text label. Takes precedence over `children`. */
7
9
  label?: string;
10
+ /** Composable label content. Used when `label` is omitted. */
11
+ children?: React.ReactNode;
8
12
  pulse?: boolean;
9
13
  showLabel?: boolean;
10
14
  className?: string;
11
15
  }
12
- declare function StatusIndicator({ type, label, pulse, showLabel, className, }: StatusIndicatorProps): React.DetailedReactHTMLElement<{
13
- className: string;
14
- role?: string | undefined;
15
- tabIndex?: number | undefined;
16
- 'aria-label'?: string | undefined;
17
- 'aria-labelledby'?: string | undefined;
18
- 'aria-describedby'?: string | undefined;
19
- 'aria-controls'?: string | undefined;
20
- 'aria-expanded'?: boolean | undefined;
21
- 'aria-selected'?: boolean | undefined;
22
- 'aria-hidden'?: boolean | undefined;
23
- 'aria-disabled'?: boolean | undefined;
24
- 'aria-pressed'?: boolean | "mixed" | undefined;
25
- 'aria-checked'?: boolean | "mixed" | undefined;
26
- 'aria-current'?: boolean | "page" | "step" | "location" | "date" | "time" | undefined;
27
- 'aria-live'?: "off" | "assertive" | "polite" | undefined;
28
- 'aria-atomic'?: boolean | undefined;
29
- }, HTMLElement>;
16
+ declare function StatusIndicator({ type, label, children, pulse, showLabel, className, }: StatusIndicatorProps): react_jsx_runtime.JSX.Element;
30
17
  declare namespace StatusIndicator {
31
18
  var displayName: string;
32
19
  }
@@ -28,14 +28,32 @@ declare function ThemeToggle({ className, variant }: ThemeToggleProps): React.De
28
28
  }, HTMLDivElement>;
29
29
 
30
30
  interface ThemeScriptProps {
31
+ /** localStorage key the ThemeProvider reads. */
31
32
  storageKey?: string;
33
+ /** Attribute strategy. `class` toggles `light`/`dark` on <html>; otherwise an HTML attribute. */
32
34
  attribute?: 'class' | 'data-theme';
35
+ /**
36
+ * Theme to apply when nothing is stored. Match this to `<ThemeProvider defaultMode>`
37
+ * so the pre-paint script and provider agree on the no-storage path. Defaults
38
+ * to `'system'` (current behaviour — OS preference wins). Issue #317.
39
+ */
40
+ defaultMode?: ThemeMode;
41
+ /**
42
+ * When `false` the inline script never reads `prefers-color-scheme`; the
43
+ * `defaultMode` is applied as-is for first-time visitors. Default `true`.
44
+ */
45
+ enableSystem?: boolean;
33
46
  }
34
47
  /**
35
48
  * Renders an inline <script> that prevents theme flash on SSR pages.
36
49
  * Place this in the <head> of your document (in Next.js layout.tsx, Remix root, etc.)
50
+ *
51
+ * Mirror the props your <ThemeProvider> uses so first-paint and React mount stay in sync:
52
+ *
53
+ * <ThemeScript defaultMode="light" storageKey="app_theme" />
54
+ * <ThemeProvider defaultMode="light" storageKey="app_theme">…</ThemeProvider>
37
55
  */
38
- declare function ThemeScript({ storageKey, attribute, }: ThemeScriptProps): React.DetailedReactHTMLElement<{
56
+ declare function ThemeScript({ storageKey, attribute, defaultMode, enableSystem, }: ThemeScriptProps): React.DetailedReactHTMLElement<{
39
57
  dangerouslySetInnerHTML: {
40
58
  __html: string;
41
59
  };
@@ -28,14 +28,32 @@ declare function ThemeToggle({ className, variant }: ThemeToggleProps): React.De
28
28
  }, HTMLDivElement>;
29
29
 
30
30
  interface ThemeScriptProps {
31
+ /** localStorage key the ThemeProvider reads. */
31
32
  storageKey?: string;
33
+ /** Attribute strategy. `class` toggles `light`/`dark` on <html>; otherwise an HTML attribute. */
32
34
  attribute?: 'class' | 'data-theme';
35
+ /**
36
+ * Theme to apply when nothing is stored. Match this to `<ThemeProvider defaultMode>`
37
+ * so the pre-paint script and provider agree on the no-storage path. Defaults
38
+ * to `'system'` (current behaviour — OS preference wins). Issue #317.
39
+ */
40
+ defaultMode?: ThemeMode;
41
+ /**
42
+ * When `false` the inline script never reads `prefers-color-scheme`; the
43
+ * `defaultMode` is applied as-is for first-time visitors. Default `true`.
44
+ */
45
+ enableSystem?: boolean;
33
46
  }
34
47
  /**
35
48
  * Renders an inline <script> that prevents theme flash on SSR pages.
36
49
  * Place this in the <head> of your document (in Next.js layout.tsx, Remix root, etc.)
50
+ *
51
+ * Mirror the props your <ThemeProvider> uses so first-paint and React mount stay in sync:
52
+ *
53
+ * <ThemeScript defaultMode="light" storageKey="app_theme" />
54
+ * <ThemeProvider defaultMode="light" storageKey="app_theme">…</ThemeProvider>
37
55
  */
38
- declare function ThemeScript({ storageKey, attribute, }: ThemeScriptProps): React.DetailedReactHTMLElement<{
56
+ declare function ThemeScript({ storageKey, attribute, defaultMode, enableSystem, }: ThemeScriptProps): React.DetailedReactHTMLElement<{
39
57
  dangerouslySetInnerHTML: {
40
58
  __html: string;
41
59
  };
@@ -0,0 +1,56 @@
1
+ import { AccessibilityProps } from '../shared/index.cjs';
2
+
3
+ type SegmentedControlSize = 'sm' | 'md';
4
+ /** Value identifying a single segment. */
5
+ type SegmentedControlValue = string;
6
+ interface SegmentedControlProps {
7
+ /** Currently selected segment value (controlled). */
8
+ value?: SegmentedControlValue;
9
+ /** Visual size of the control. */
10
+ size?: SegmentedControlSize;
11
+ }
12
+ interface SegmentedControlAPI {
13
+ /** ARIA attributes to spread on the group element. */
14
+ ariaProps: Partial<AccessibilityProps>;
15
+ /** Data attributes for CSS styling hooks. */
16
+ dataAttributes: Record<string, string>;
17
+ }
18
+ /**
19
+ * Build the framework-agnostic group props for a segmented control.
20
+ *
21
+ * Returns `role="radiogroup"` plus data attributes; adapters spread these
22
+ * onto their group element and handle their own rendering/state.
23
+ */
24
+ declare function createSegmentedControl(props?: SegmentedControlProps): SegmentedControlAPI;
25
+ /**
26
+ * Pure keyboard-navigation rule shared by every adapter.
27
+ *
28
+ * Given the current index, the pressed key, and the item count, returns the
29
+ * index that focus/selection should move to. Arrow keys wrap; Home/End jump
30
+ * to the ends. Unhandled keys (or an empty group) return `current` unchanged.
31
+ *
32
+ * - ArrowRight / ArrowDown → next (wraps to 0 past the end)
33
+ * - ArrowLeft / ArrowUp → previous (wraps to last before 0)
34
+ * - Home → first
35
+ * - End → last
36
+ */
37
+ declare function getNextSegmentIndex(current: number, key: string, count: number): number;
38
+
39
+ /** Pill-shaped container that holds the segments (`role="radiogroup"`). */
40
+ declare const segmentedControlVariants: (props?: ({
41
+ size?: "sm" | "md" | undefined;
42
+ } & {
43
+ className?: string;
44
+ }) | undefined) => string;
45
+ /**
46
+ * A single segment (`role="radio"`). The `state` variant carries the
47
+ * active vs inactive visual treatment so adapters never inline these classes.
48
+ */
49
+ declare const segmentedControlItemVariants: (props?: ({
50
+ size?: "sm" | "md" | undefined;
51
+ state?: "checked" | "unchecked" | undefined;
52
+ } & {
53
+ className?: string;
54
+ }) | undefined) => string;
55
+
56
+ export { type SegmentedControlAPI, type SegmentedControlProps, type SegmentedControlSize, type SegmentedControlValue, createSegmentedControl, getNextSegmentIndex, segmentedControlItemVariants, segmentedControlVariants };
@@ -0,0 +1,56 @@
1
+ import { AccessibilityProps } from '../shared/index.js';
2
+
3
+ type SegmentedControlSize = 'sm' | 'md';
4
+ /** Value identifying a single segment. */
5
+ type SegmentedControlValue = string;
6
+ interface SegmentedControlProps {
7
+ /** Currently selected segment value (controlled). */
8
+ value?: SegmentedControlValue;
9
+ /** Visual size of the control. */
10
+ size?: SegmentedControlSize;
11
+ }
12
+ interface SegmentedControlAPI {
13
+ /** ARIA attributes to spread on the group element. */
14
+ ariaProps: Partial<AccessibilityProps>;
15
+ /** Data attributes for CSS styling hooks. */
16
+ dataAttributes: Record<string, string>;
17
+ }
18
+ /**
19
+ * Build the framework-agnostic group props for a segmented control.
20
+ *
21
+ * Returns `role="radiogroup"` plus data attributes; adapters spread these
22
+ * onto their group element and handle their own rendering/state.
23
+ */
24
+ declare function createSegmentedControl(props?: SegmentedControlProps): SegmentedControlAPI;
25
+ /**
26
+ * Pure keyboard-navigation rule shared by every adapter.
27
+ *
28
+ * Given the current index, the pressed key, and the item count, returns the
29
+ * index that focus/selection should move to. Arrow keys wrap; Home/End jump
30
+ * to the ends. Unhandled keys (or an empty group) return `current` unchanged.
31
+ *
32
+ * - ArrowRight / ArrowDown → next (wraps to 0 past the end)
33
+ * - ArrowLeft / ArrowUp → previous (wraps to last before 0)
34
+ * - Home → first
35
+ * - End → last
36
+ */
37
+ declare function getNextSegmentIndex(current: number, key: string, count: number): number;
38
+
39
+ /** Pill-shaped container that holds the segments (`role="radiogroup"`). */
40
+ declare const segmentedControlVariants: (props?: ({
41
+ size?: "sm" | "md" | undefined;
42
+ } & {
43
+ className?: string;
44
+ }) | undefined) => string;
45
+ /**
46
+ * A single segment (`role="radio"`). The `state` variant carries the
47
+ * active vs inactive visual treatment so adapters never inline these classes.
48
+ */
49
+ declare const segmentedControlItemVariants: (props?: ({
50
+ size?: "sm" | "md" | undefined;
51
+ state?: "checked" | "unchecked" | undefined;
52
+ } & {
53
+ className?: string;
54
+ }) | undefined) => string;
55
+
56
+ export { type SegmentedControlAPI, type SegmentedControlProps, type SegmentedControlSize, type SegmentedControlValue, createSegmentedControl, getNextSegmentIndex, segmentedControlItemVariants, segmentedControlVariants };
@@ -0,0 +1,55 @@
1
+ import { AccessibilityProps } from '../shared/index.cjs';
2
+
3
+ type SeparatorOrientation = 'horizontal' | 'vertical';
4
+ interface SeparatorProps {
5
+ /** Orientation of the separator. Defaults to `'horizontal'`. */
6
+ orientation?: SeparatorOrientation;
7
+ /**
8
+ * When `true` (the default) the separator is purely visual and is hidden
9
+ * from assistive tech (`role="none"`). When `false` it is exposed as a
10
+ * semantic `role="separator"` with the appropriate `aria-orientation`.
11
+ */
12
+ decorative?: boolean;
13
+ }
14
+ /**
15
+ * ARIA attributes for a separator. Extends the shared base with
16
+ * `aria-orientation`, which is specific to the `separator` role.
17
+ */
18
+ interface SeparatorAriaProps extends Partial<AccessibilityProps> {
19
+ 'aria-orientation'?: SeparatorOrientation;
20
+ }
21
+ interface SeparatorAPI {
22
+ /** ARIA attributes to spread on the element. */
23
+ ariaProps: SeparatorAriaProps;
24
+ /** Data attributes for CSS styling hooks. */
25
+ dataAttributes: Record<string, string>;
26
+ }
27
+ /**
28
+ * Headless separator core — computes ARIA semantics and data attributes for
29
+ * a separator rule. JSX-free so it can be shared across framework adapters.
30
+ *
31
+ * Per ARIA, a decorative separator must not be announced (`role="none"`),
32
+ * while a semantic one exposes `role="separator"` and `aria-orientation`.
33
+ */
34
+ declare function createSeparator(props?: SeparatorProps): SeparatorAPI;
35
+
36
+ /**
37
+ * Visual variants for the separator rule.
38
+ *
39
+ * - `orientation: horizontal` → a full-width 1px line.
40
+ * - `orientation: vertical` → a full-height 1px line.
41
+ * - `labeled` → flex layout used by the labeled-divider variant, which
42
+ * arranges a centered label between two flanking lines.
43
+ */
44
+ declare const separatorVariants: (props?: ({
45
+ orientation?: "horizontal" | "vertical" | undefined;
46
+ labeled?: "true" | "false" | undefined;
47
+ } & {
48
+ className?: string;
49
+ }) | undefined) => string;
50
+ /** Class for each flanking line in the labeled-divider variant. */
51
+ declare const separatorLineClass = "h-px flex-1 bg-border";
52
+ /** Class for the centered label in the labeled-divider variant. */
53
+ declare const separatorLabelClass = "px-3 text-xs uppercase tracking-wide text-muted-foreground";
54
+
55
+ export { type SeparatorAPI, type SeparatorOrientation, type SeparatorProps, createSeparator, separatorLabelClass, separatorLineClass, separatorVariants };
@@ -0,0 +1,55 @@
1
+ import { AccessibilityProps } from '../shared/index.js';
2
+
3
+ type SeparatorOrientation = 'horizontal' | 'vertical';
4
+ interface SeparatorProps {
5
+ /** Orientation of the separator. Defaults to `'horizontal'`. */
6
+ orientation?: SeparatorOrientation;
7
+ /**
8
+ * When `true` (the default) the separator is purely visual and is hidden
9
+ * from assistive tech (`role="none"`). When `false` it is exposed as a
10
+ * semantic `role="separator"` with the appropriate `aria-orientation`.
11
+ */
12
+ decorative?: boolean;
13
+ }
14
+ /**
15
+ * ARIA attributes for a separator. Extends the shared base with
16
+ * `aria-orientation`, which is specific to the `separator` role.
17
+ */
18
+ interface SeparatorAriaProps extends Partial<AccessibilityProps> {
19
+ 'aria-orientation'?: SeparatorOrientation;
20
+ }
21
+ interface SeparatorAPI {
22
+ /** ARIA attributes to spread on the element. */
23
+ ariaProps: SeparatorAriaProps;
24
+ /** Data attributes for CSS styling hooks. */
25
+ dataAttributes: Record<string, string>;
26
+ }
27
+ /**
28
+ * Headless separator core — computes ARIA semantics and data attributes for
29
+ * a separator rule. JSX-free so it can be shared across framework adapters.
30
+ *
31
+ * Per ARIA, a decorative separator must not be announced (`role="none"`),
32
+ * while a semantic one exposes `role="separator"` and `aria-orientation`.
33
+ */
34
+ declare function createSeparator(props?: SeparatorProps): SeparatorAPI;
35
+
36
+ /**
37
+ * Visual variants for the separator rule.
38
+ *
39
+ * - `orientation: horizontal` → a full-width 1px line.
40
+ * - `orientation: vertical` → a full-height 1px line.
41
+ * - `labeled` → flex layout used by the labeled-divider variant, which
42
+ * arranges a centered label between two flanking lines.
43
+ */
44
+ declare const separatorVariants: (props?: ({
45
+ orientation?: "horizontal" | "vertical" | undefined;
46
+ labeled?: "true" | "false" | undefined;
47
+ } & {
48
+ className?: string;
49
+ }) | undefined) => string;
50
+ /** Class for each flanking line in the labeled-divider variant. */
51
+ declare const separatorLineClass = "h-px flex-1 bg-border";
52
+ /** Class for the centered label in the labeled-divider variant. */
53
+ declare const separatorLabelClass = "px-3 text-xs uppercase tracking-wide text-muted-foreground";
54
+
55
+ export { type SeparatorAPI, type SeparatorOrientation, type SeparatorProps, createSeparator, separatorLabelClass, separatorLineClass, separatorVariants };
@@ -0,0 +1,47 @@
1
+ type SocialProvider = 'google' | 'github' | 'microsoft' | 'apple';
2
+ /** "Continue with …" label shown on each provider's button. */
3
+ declare const PROVIDER_LABELS: Record<SocialProvider, string>;
4
+ /**
5
+ * Which providers render their brand mark monochrome (currentColor). GitHub and
6
+ * Apple are monochrome by design so they read correctly on dark/outline
7
+ * surfaces; Google and Microsoft keep their full brand color.
8
+ */
9
+ declare const PROVIDER_MONO: Record<SocialProvider, boolean>;
10
+ interface SocialAuthButtonProps {
11
+ /** Identity provider this button authenticates against. */
12
+ provider: SocialProvider;
13
+ }
14
+ interface SocialAuthButtonAPI {
15
+ /** Data attributes for CSS styling hooks. */
16
+ dataAttributes: Record<string, string>;
17
+ /** "Continue with …" label for the provider. */
18
+ label: string;
19
+ /** Whether the brand mark should render monochrome. */
20
+ mono: boolean;
21
+ }
22
+ /**
23
+ * Framework-agnostic core for a social sign-in button. Returns the provider
24
+ * label, monochrome hint, and the `data-provider` styling hook. No React/JSX.
25
+ */
26
+ declare function createSocialAuthButton(props: SocialAuthButtonProps): SocialAuthButtonAPI;
27
+
28
+ /** Wrapper around an individual social auth button (positions the lastUsed badge). */
29
+ declare const socialAuthButtonVariants: (props?: ({
30
+ [x: string]: string | undefined;
31
+ } & {
32
+ className?: string;
33
+ }) | undefined) => string;
34
+ /** Responsive grid wrapper: one column on mobile, two columns from `sm` up. */
35
+ declare const socialAuthRowVariants: (props?: ({
36
+ [x: string]: string | undefined;
37
+ } & {
38
+ className?: string;
39
+ }) | undefined) => string;
40
+ /** Floating "Last used" badge anchored to the top-right of a button. */
41
+ declare const lastUsedBadgeVariants: (props?: ({
42
+ [x: string]: string | undefined;
43
+ } & {
44
+ className?: string;
45
+ }) | undefined) => string;
46
+
47
+ export { PROVIDER_LABELS, PROVIDER_MONO, type SocialAuthButtonAPI, type SocialAuthButtonProps, type SocialProvider, createSocialAuthButton, lastUsedBadgeVariants, socialAuthButtonVariants, socialAuthRowVariants };
@@ -0,0 +1,47 @@
1
+ type SocialProvider = 'google' | 'github' | 'microsoft' | 'apple';
2
+ /** "Continue with …" label shown on each provider's button. */
3
+ declare const PROVIDER_LABELS: Record<SocialProvider, string>;
4
+ /**
5
+ * Which providers render their brand mark monochrome (currentColor). GitHub and
6
+ * Apple are monochrome by design so they read correctly on dark/outline
7
+ * surfaces; Google and Microsoft keep their full brand color.
8
+ */
9
+ declare const PROVIDER_MONO: Record<SocialProvider, boolean>;
10
+ interface SocialAuthButtonProps {
11
+ /** Identity provider this button authenticates against. */
12
+ provider: SocialProvider;
13
+ }
14
+ interface SocialAuthButtonAPI {
15
+ /** Data attributes for CSS styling hooks. */
16
+ dataAttributes: Record<string, string>;
17
+ /** "Continue with …" label for the provider. */
18
+ label: string;
19
+ /** Whether the brand mark should render monochrome. */
20
+ mono: boolean;
21
+ }
22
+ /**
23
+ * Framework-agnostic core for a social sign-in button. Returns the provider
24
+ * label, monochrome hint, and the `data-provider` styling hook. No React/JSX.
25
+ */
26
+ declare function createSocialAuthButton(props: SocialAuthButtonProps): SocialAuthButtonAPI;
27
+
28
+ /** Wrapper around an individual social auth button (positions the lastUsed badge). */
29
+ declare const socialAuthButtonVariants: (props?: ({
30
+ [x: string]: string | undefined;
31
+ } & {
32
+ className?: string;
33
+ }) | undefined) => string;
34
+ /** Responsive grid wrapper: one column on mobile, two columns from `sm` up. */
35
+ declare const socialAuthRowVariants: (props?: ({
36
+ [x: string]: string | undefined;
37
+ } & {
38
+ className?: string;
39
+ }) | undefined) => string;
40
+ /** Floating "Last used" badge anchored to the top-right of a button. */
41
+ declare const lastUsedBadgeVariants: (props?: ({
42
+ [x: string]: string | undefined;
43
+ } & {
44
+ className?: string;
45
+ }) | undefined) => string;
46
+
47
+ export { PROVIDER_LABELS, PROVIDER_MONO, type SocialAuthButtonAPI, type SocialAuthButtonProps, type SocialProvider, createSocialAuthButton, lastUsedBadgeVariants, socialAuthButtonVariants, socialAuthRowVariants };
@@ -43,7 +43,41 @@ declare function createTheme(config?: ThemeConfig, storage?: StorageAdapter, med
43
43
  * Inject this as a <script> tag in the <head> before any CSS.
44
44
  * Works with any framework (React, Astro, plain HTML).
45
45
  */
46
- declare function getThemeScript(storageKey?: string, attribute?: 'class' | 'data-theme'): string;
46
+
47
+ interface ThemeScriptOptions {
48
+ /** localStorage key the corresponding ThemeProvider reads. */
49
+ storageKey?: string;
50
+ /** Attribute strategy: 'class' toggles `light`/`dark` classes; otherwise an HTML attribute. */
51
+ attribute?: 'class' | 'data-theme';
52
+ /**
53
+ * Theme to apply when nothing is stored AND `enableSystem` is false
54
+ * (or `defaultMode` is explicitly 'light'/'dark'). Match this to your
55
+ * ThemeProvider's `defaultMode` so the pre-paint script and provider agree.
56
+ * Defaults to `'system'` — current behavior, OS preference wins.
57
+ *
58
+ * Issue #317.
59
+ */
60
+ defaultMode?: ThemeMode;
61
+ /**
62
+ * When `true` (default) and `defaultMode === 'system'`, the script falls
63
+ * through to `prefers-color-scheme`. When `false`, the script applies
64
+ * `defaultMode` directly and never reads the OS preference.
65
+ */
66
+ enableSystem?: boolean;
67
+ }
68
+ /**
69
+ * Build the pre-paint inline script. Mirrors the resolution order used by
70
+ * the React/Astro `ThemeProvider`:
71
+ *
72
+ * 1. stored value (light|dark|system)
73
+ * 2. if no stored value: `defaultMode` (light|dark applied as-is)
74
+ * 3. if stored or default is 'system' AND `enableSystem`: matchMedia
75
+ * 4. else: 'light'
76
+ *
77
+ * Back-compat: with no options the script behaves exactly as before —
78
+ * stored value, then matchMedia, then 'light'.
79
+ */
80
+ declare function getThemeScript(storageKeyOrOptions?: string | ThemeScriptOptions, attribute?: 'class' | 'data-theme'): string;
47
81
 
48
82
  /**
49
83
  * Browser DOM adapters for the theme machine.
@@ -43,7 +43,41 @@ declare function createTheme(config?: ThemeConfig, storage?: StorageAdapter, med
43
43
  * Inject this as a <script> tag in the <head> before any CSS.
44
44
  * Works with any framework (React, Astro, plain HTML).
45
45
  */
46
- declare function getThemeScript(storageKey?: string, attribute?: 'class' | 'data-theme'): string;
46
+
47
+ interface ThemeScriptOptions {
48
+ /** localStorage key the corresponding ThemeProvider reads. */
49
+ storageKey?: string;
50
+ /** Attribute strategy: 'class' toggles `light`/`dark` classes; otherwise an HTML attribute. */
51
+ attribute?: 'class' | 'data-theme';
52
+ /**
53
+ * Theme to apply when nothing is stored AND `enableSystem` is false
54
+ * (or `defaultMode` is explicitly 'light'/'dark'). Match this to your
55
+ * ThemeProvider's `defaultMode` so the pre-paint script and provider agree.
56
+ * Defaults to `'system'` — current behavior, OS preference wins.
57
+ *
58
+ * Issue #317.
59
+ */
60
+ defaultMode?: ThemeMode;
61
+ /**
62
+ * When `true` (default) and `defaultMode === 'system'`, the script falls
63
+ * through to `prefers-color-scheme`. When `false`, the script applies
64
+ * `defaultMode` directly and never reads the OS preference.
65
+ */
66
+ enableSystem?: boolean;
67
+ }
68
+ /**
69
+ * Build the pre-paint inline script. Mirrors the resolution order used by
70
+ * the React/Astro `ThemeProvider`:
71
+ *
72
+ * 1. stored value (light|dark|system)
73
+ * 2. if no stored value: `defaultMode` (light|dark applied as-is)
74
+ * 3. if stored or default is 'system' AND `enableSystem`: matchMedia
75
+ * 4. else: 'light'
76
+ *
77
+ * Back-compat: with no options the script behaves exactly as before —
78
+ * stored value, then matchMedia, then 'light'.
79
+ */
80
+ declare function getThemeScript(storageKeyOrOptions?: string | ThemeScriptOptions, attribute?: 'class' | 'data-theme'): string;
47
81
 
48
82
  /**
49
83
  * Browser DOM adapters for the theme machine.
package/dist/theme.cjs CHANGED
@@ -90,8 +90,29 @@ function createTheme(config = {}, storage, mediaQuery) {
90
90
  }
91
91
  };
92
92
  }
93
- function getThemeScript(storageKey = "rfr-theme", attribute = "class") {
94
- return `(function(){try{var m=localStorage.getItem('${storageKey}');var s=window.matchMedia('(prefers-color-scheme:dark)').matches;var t=m==='dark'||(m!=='light'&&s)?'dark':'light';var d=document.documentElement;${attribute === "class" ? "d.classList.remove('light','dark');d.classList.add(t);" : `d.setAttribute('${attribute}',t);`}d.style.colorScheme=t;}catch(e){}})()`;
93
+ function getThemeScript(storageKeyOrOptions = "rfr-theme", attribute = "class") {
94
+ const opts = typeof storageKeyOrOptions === "string" ? {
95
+ storageKey: storageKeyOrOptions,
96
+ attribute,
97
+ defaultMode: "system",
98
+ enableSystem: true
99
+ } : {
100
+ storageKey: storageKeyOrOptions.storageKey ?? "rfr-theme",
101
+ attribute: storageKeyOrOptions.attribute ?? "class",
102
+ defaultMode: storageKeyOrOptions.defaultMode ?? "system",
103
+ enableSystem: storageKeyOrOptions.enableSystem ?? true
104
+ };
105
+ const noSystemFallback = opts.defaultMode === "light" || opts.defaultMode === "dark" || !opts.enableSystem;
106
+ const safeDefault = opts.defaultMode === "dark" ? "dark" : "light";
107
+ const resolveExpr = noSystemFallback ? (
108
+ // Stored wins → else hard default. No matchMedia call at all.
109
+ `var t=m==='dark'?'dark':(m==='light'?'light':'${safeDefault}');`
110
+ ) : (
111
+ // Original behaviour: stored → else matchMedia → else light.
112
+ `var s=window.matchMedia('(prefers-color-scheme:dark)').matches;var t=m==='dark'||(m!=='light'&&s)?'dark':'light';`
113
+ );
114
+ const applyExpr = opts.attribute === "class" ? "d.classList.remove('light','dark');d.classList.add(t);" : `d.setAttribute('${opts.attribute}',t);`;
115
+ return `(function(){try{var m=localStorage.getItem('${opts.storageKey}');${resolveExpr}var d=document.documentElement;${applyExpr}d.style.colorScheme=t;}catch(e){}})()`;
95
116
  }
96
117
  function createLocalStorageAdapter() {
97
118
  return {
@@ -330,11 +351,13 @@ function ThemeToggle({ className, variant = "segmented" }) {
330
351
  }
331
352
  function ThemeScript({
332
353
  storageKey = "rfr-theme",
333
- attribute = "class"
354
+ attribute = "class",
355
+ defaultMode = "system",
356
+ enableSystem = true
334
357
  }) {
335
358
  return React2__namespace.createElement("script", {
336
359
  dangerouslySetInnerHTML: {
337
- __html: getThemeScript(storageKey, attribute)
360
+ __html: getThemeScript({ storageKey, attribute, defaultMode, enableSystem })
338
361
  }
339
362
  });
340
363
  }