@thewhileloop/whileui 2.0.0 → 4.0.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 (74) hide show
  1. package/README.md +135 -70
  2. package/dist/blocks/commerce/metric-card.d.ts +9 -29
  3. package/dist/blocks/datepicker/date-range-picker-modal.d.ts +1 -1
  4. package/dist/blocks/datepicker/date-range-picker-modal.js +6 -14
  5. package/dist/blocks/datepicker/datepicker-modal.d.ts +1 -1
  6. package/dist/blocks/datepicker/datepicker-modal.js +6 -12
  7. package/dist/blocks/datepicker/index.d.ts +1 -0
  8. package/dist/blocks/datepicker/index.js +1 -0
  9. package/dist/blocks/datepicker/time-picker-modal.d.ts +43 -0
  10. package/dist/blocks/datepicker/time-picker-modal.js +187 -0
  11. package/dist/blocks/layout/smart-input.d.ts +3 -2
  12. package/dist/blocks/layout/smart-input.js +33 -18
  13. package/dist/blocks/media/smart-image.d.ts +39 -98
  14. package/dist/blocks/navigation/drawer-menu.js +88 -72
  15. package/dist/components/alert/alert.d.ts +23 -55
  16. package/dist/components/alert/alert.js +1 -1
  17. package/dist/components/alert-dialog/alert-dialog.js +1 -4
  18. package/dist/components/avatar/avatar.d.ts +18 -45
  19. package/dist/components/avatar/avatar.js +1 -1
  20. package/dist/components/badge/badge.d.ts +84 -212
  21. package/dist/components/button/button.d.ts +69 -188
  22. package/dist/components/card/card.d.ts +29 -73
  23. package/dist/components/card/card.js +1 -1
  24. package/dist/components/container/container.d.ts +24 -96
  25. package/dist/components/data-row/data-row.d.ts +18 -38
  26. package/dist/components/data-row/data-row.js +1 -1
  27. package/dist/components/fab/fab.d.ts +87 -0
  28. package/dist/components/fab/fab.js +59 -0
  29. package/dist/components/fab/index.d.ts +1 -0
  30. package/dist/components/fab/index.js +1 -0
  31. package/dist/components/form-field/form-field.d.ts +31 -87
  32. package/dist/components/form-field/form-field.js +1 -1
  33. package/dist/components/hover-card/hover-card.d.ts +3 -2
  34. package/dist/components/input/input.d.ts +18 -31
  35. package/dist/components/input/input.js +20 -8
  36. package/dist/components/label/label.d.ts +3 -3
  37. package/dist/components/labeled-field/labeled-field.d.ts +3 -2
  38. package/dist/components/numeric-input/numeric-input.d.ts +27 -82
  39. package/dist/components/numeric-input/numeric-input.js +79 -80
  40. package/dist/components/otp-input/otp-input.d.ts +21 -65
  41. package/dist/components/popover/popover.d.ts +4 -3
  42. package/dist/components/pressable/pressable.d.ts +3 -3
  43. package/dist/components/progress/progress.d.ts +15 -39
  44. package/dist/components/row/row.d.ts +63 -163
  45. package/dist/components/segmented-control/segmented-control.d.ts +69 -241
  46. package/dist/components/select/select.d.ts +10 -22
  47. package/dist/components/select/select.js +2 -7
  48. package/dist/components/separator/separator.d.ts +3 -3
  49. package/dist/components/skeleton/skeleton.d.ts +9 -29
  50. package/dist/components/spinner/spinner.d.ts +12 -36
  51. package/dist/components/stack/stack.d.ts +63 -163
  52. package/dist/components/tabs/tabs.d.ts +9 -29
  53. package/dist/components/text/text.d.ts +51 -131
  54. package/dist/components/textarea/textarea.d.ts +15 -39
  55. package/dist/components/textarea/textarea.js +3 -3
  56. package/dist/components/toast/toast.d.ts +12 -36
  57. package/dist/components/toggle/toggle.d.ts +42 -138
  58. package/dist/components/toggle-group/toggle-group.d.ts +42 -138
  59. package/dist/components/tooltip/tooltip.d.ts +3 -2
  60. package/dist/components/view/view.d.ts +3 -3
  61. package/dist/index.d.ts +2 -1
  62. package/dist/index.js +2 -1
  63. package/dist/lib/focus-ring.d.ts +10 -0
  64. package/dist/lib/focus-ring.js +10 -0
  65. package/dist/lib/interaction-tokens.d.ts +24 -1
  66. package/dist/lib/interaction-tokens.js +26 -44
  67. package/dist/lib/motion-policy.js +2 -2
  68. package/dist/lib/ref-types.d.ts +3 -0
  69. package/dist/lib/ref-types.js +1 -0
  70. package/dist/lib/theme-bridge.d.ts +4 -2
  71. package/dist/lib/theme-bridge.js +13 -9
  72. package/dist/lib/theme-presets.d.ts +26 -0
  73. package/dist/lib/theme-presets.js +28 -0
  74. package/package.json +29 -28
@@ -8,7 +8,6 @@ export interface ThemeBridgeProps {
8
8
  mode?: ThemeMode;
9
9
  initialMode?: ThemeMode;
10
10
  adapter?: ThemeBridgeAdapter;
11
- onModeChange?: (mode: ThemeMode) => void;
12
11
  }
13
12
  export interface UseThemeBridgeOptions {
14
13
  initialMode?: ThemeMode;
@@ -24,5 +23,8 @@ export declare function applyThemeMode(mode: ThemeMode): void;
24
23
  export declare function resolveThemeMode(adapter?: ThemeBridgeAdapter, fallback?: ThemeMode): Promise<ThemeMode>;
25
24
  export declare function syncThemeMode(mode: ThemeMode, adapter?: ThemeBridgeAdapter): Promise<ThemeMode>;
26
25
  export declare function useThemeBridge({ initialMode, adapter, }?: UseThemeBridgeOptions): UseThemeBridgeResult;
27
- export declare function ThemeBridge({ mode: controlledMode, initialMode, adapter, onModeChange, }: ThemeBridgeProps): null;
26
+ export declare function ThemeBridge({ mode, initialMode, adapter }: ThemeBridgeProps): import("react").FunctionComponentElement<Pick<ThemeBridgeProps, "initialMode" | "adapter">> | import("react").FunctionComponentElement<{
27
+ mode: ThemeMode;
28
+ adapter?: ThemeBridgeAdapter;
29
+ }>;
28
30
  export {};
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useMemo, useState } from 'react';
1
+ import { createElement, useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import { Uniwind, useUniwind } from 'uniwind';
3
3
  const modeCycle = ['light', 'dark', 'system'];
4
4
  export function applyThemeMode(mode) {
@@ -74,14 +74,18 @@ export function useThemeBridge({ initialMode = 'system', adapter, } = {}) {
74
74
  cycleMode,
75
75
  }), [cycleMode, mode, theme]);
76
76
  }
77
- export function ThemeBridge({ mode: controlledMode, initialMode = 'system', adapter, onModeChange, }) {
78
- const { mode, setMode } = useThemeBridge({ initialMode, adapter });
79
- const effectiveMode = controlledMode ?? mode;
77
+ function ControlledThemeBridge({ mode, adapter, }) {
80
78
  useEffect(() => {
81
- setMode(effectiveMode);
82
- }, [effectiveMode, setMode]);
83
- useEffect(() => {
84
- onModeChange?.(effectiveMode);
85
- }, [effectiveMode, onModeChange]);
79
+ void syncThemeMode(mode, adapter);
80
+ }, [adapter, mode]);
81
+ return null;
82
+ }
83
+ function UncontrolledThemeBridge({ initialMode, adapter, }) {
84
+ useThemeBridge({ initialMode, adapter });
86
85
  return null;
87
86
  }
87
+ export function ThemeBridge({ mode, initialMode = 'system', adapter }) {
88
+ return mode === undefined
89
+ ? createElement(UncontrolledThemeBridge, { initialMode, adapter })
90
+ : createElement(ControlledThemeBridge, { mode, adapter });
91
+ }
@@ -1,4 +1,5 @@
1
1
  import { type ThemeColors } from './theme-contract';
2
+ import { type ThemeBaseColors } from './theme-derive';
2
3
  import { type VisualTokens } from './visual-token-contract';
3
4
  /**
4
5
  * Canonical full-package theme presets.
@@ -15,6 +16,31 @@ export interface ThemePreset {
15
16
  /** Visual token overrides; unset keys keep contract fallbacks. */
16
17
  visual: Partial<VisualTokens>;
17
18
  }
19
+ /**
20
+ * Build a preset from the 25 base colors, deriving the other 27.
21
+ *
22
+ * Prefer this to writing a `ThemePreset` literal. `visual` has always been
23
+ * `Partial`, but `light` and `dark` are the full 52-key `ThemeColors`, so the
24
+ * literal form asks an author for every active variant, soft variant, overlay,
25
+ * surface, interaction state and shadow — values `deriveThemeColors` already
26
+ * computes from the palette. Nothing in the literal's type points at that helper,
27
+ * and the predictable result is a hand-written derivation that drifts from the
28
+ * library's own. The Atelier preset below is 110 lines for this reason.
29
+ *
30
+ * Override a derived value by spreading the result:
31
+ *
32
+ * ```ts
33
+ * const preset = createThemePreset({ name, description, light, dark });
34
+ * preset.dark.overlay = 'rgba(0, 0, 0, 0.9)';
35
+ * ```
36
+ */
37
+ export declare function createThemePreset(input: {
38
+ name: string;
39
+ description: string;
40
+ light: ThemeBaseColors;
41
+ dark: ThemeBaseColors;
42
+ visual?: Partial<VisualTokens>;
43
+ }): ThemePreset;
18
44
  export declare const WHILEUI_PRESET_SOFT: ThemePreset;
19
45
  export declare const WHILEUI_PRESET_ATELIER: ThemePreset;
20
46
  export declare const WHILEUI_THEME_PRESETS: readonly ThemePreset[];
@@ -1,5 +1,33 @@
1
1
  import { THEME_TOKEN_SPECS, WHILEUI_DARK_THEME_COLORS, WHILEUI_LIGHT_THEME_COLORS, } from './theme-contract';
2
+ import { deriveThemeColors } from './theme-derive';
2
3
  import { VISUAL_TOKEN_SPECS } from './visual-token-contract';
4
+ /**
5
+ * Build a preset from the 25 base colors, deriving the other 27.
6
+ *
7
+ * Prefer this to writing a `ThemePreset` literal. `visual` has always been
8
+ * `Partial`, but `light` and `dark` are the full 52-key `ThemeColors`, so the
9
+ * literal form asks an author for every active variant, soft variant, overlay,
10
+ * surface, interaction state and shadow — values `deriveThemeColors` already
11
+ * computes from the palette. Nothing in the literal's type points at that helper,
12
+ * and the predictable result is a hand-written derivation that drifts from the
13
+ * library's own. The Atelier preset below is 110 lines for this reason.
14
+ *
15
+ * Override a derived value by spreading the result:
16
+ *
17
+ * ```ts
18
+ * const preset = createThemePreset({ name, description, light, dark });
19
+ * preset.dark.overlay = 'rgba(0, 0, 0, 0.9)';
20
+ * ```
21
+ */
22
+ export function createThemePreset(input) {
23
+ return {
24
+ name: input.name,
25
+ description: input.description,
26
+ light: deriveThemeColors(input.light, 'light'),
27
+ dark: deriveThemeColors(input.dark, 'dark'),
28
+ visual: input.visual ?? {},
29
+ };
30
+ }
3
31
  // Rounded, airy, frosted. Matches the contract fallbacks.
4
32
  export const WHILEUI_PRESET_SOFT = {
5
33
  name: 'soft',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thewhileloop/whileui",
3
- "version": "2.0.0",
3
+ "version": "4.0.0",
4
4
  "description": "WhileUI Native — Copy-paste components for React Native. You own the code.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -60,25 +60,25 @@
60
60
  "test:watch": "jest --watch"
61
61
  },
62
62
  "peerDependencies": {
63
- "@rn-primitives/hooks": ">=1.0.0",
64
- "@rn-primitives/hover-card": ">=1.0.0",
65
- "@rn-primitives/popover": ">=1.0.0",
66
- "@rn-primitives/portal": ">=1.0.0",
67
- "@rn-primitives/select": ">=1.0.0",
68
- "@rn-primitives/slot": ">=1.0.0",
69
- "@rn-primitives/tooltip": ">=1.0.0",
70
- "expo": ">=57.0.0",
71
- "expo-blur": ">=57.0.0",
72
- "expo-image": ">=57.0.0",
73
- "react": ">=19.2.0",
74
- "react-native": ">=0.86.0",
75
- "react-native-gesture-handler": ">=2.32.0",
76
- "react-native-reanimated": ">=4.5.0",
77
- "react-native-safe-area-context": ">=5.7.0",
78
- "react-native-screens": ">=4.26.0",
63
+ "@rn-primitives/hooks": ">=1.5.2",
64
+ "@rn-primitives/hover-card": ">=1.5.2",
65
+ "@rn-primitives/popover": ">=1.5.2",
66
+ "@rn-primitives/portal": ">=1.5.3",
67
+ "@rn-primitives/select": ">=1.5.2",
68
+ "@rn-primitives/slot": ">=1.5.2",
69
+ "@rn-primitives/tooltip": ">=1.5.2",
70
+ "expo": ">=58.0.0",
71
+ "expo-blur": ">=58.0.0",
72
+ "expo-image": ">=58.0.0",
73
+ "react": ">=19.3.0",
74
+ "react-native": ">=0.88.0",
75
+ "react-native-gesture-handler": ">=3.3.0",
76
+ "react-native-reanimated": ">=4.7.0",
77
+ "react-native-safe-area-context": ">=5.10.0",
78
+ "react-native-screens": ">=4.30.0",
79
79
  "tailwindcss": ">=4.0.0",
80
80
  "uniwind": ">=1.12.0",
81
- "react-native-worklets": ">=0.10.0"
81
+ "react-native-worklets": ">=0.13.0"
82
82
  },
83
83
  "peerDependenciesMeta": {
84
84
  "expo-blur": {
@@ -89,19 +89,20 @@
89
89
  "clsx": "^2.1.0",
90
90
  "culori": "^4.0.2",
91
91
  "react-native-calendars": "^1.1314.0",
92
- "tailwind-merge": "^3.0.0",
93
- "tailwind-variants": "^0.3.0"
92
+ "tailwind-merge": "^3.7.0",
93
+ "tailwind-variants": "^3.3.1"
94
94
  },
95
95
  "devDependencies": {
96
- "@testing-library/react-native": "^14.0.1",
96
+ "@react-native/jest-preset": "0.88.0",
97
+ "@testing-library/react-native": "^14.1.0",
97
98
  "@types/culori": "^4.0.1",
98
- "@types/jest": "^29.5.14",
99
- "@types/react": "~19.2.0",
100
- "expo-image": "~57.0.5",
101
- "jest": "^29.7.0",
102
- "jest-expo": "~57.0.5",
103
- "react-native-screens": "~4.26.0",
104
- "test-renderer": "^1.2.0",
99
+ "@types/jest": "^30.0.0",
100
+ "@types/react": "~19.3.0",
101
+ "expo-image": "~58.0.15",
102
+ "jest": "^30.5.2",
103
+ "jest-expo": "~58.0.11",
104
+ "react-native-screens": "~4.30.0",
105
+ "test-renderer": "^1.3.1",
105
106
  "typescript": "~6.0.3"
106
107
  }
107
108
  }