@hexdspace/react 0.0.14 → 0.0.16

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.
@@ -0,0 +1,108 @@
1
+ @import 'tailwindcss';
2
+ @import 'utils/custom-scrollbar.css';
3
+ @import 'primitive.css';
4
+ @import 'semantic.css';
5
+ @import 'component.css';
6
+
7
+ @plugin 'tailwind-scrollbar';
8
+
9
+ /* Tailwind aliases */
10
+ @theme {
11
+ /* radii */
12
+ --radius-none: var(--shape-radius-0);
13
+ --radius-xs: var(--shape-radius-5);
14
+ --radius-sm: var(--shape-radius-10);
15
+ --radius-md: var(--shape-radius-20);
16
+ --radius-lg: var(--shape-radius-30);
17
+ --radius-xl: var(--shape-radius-40);
18
+ --radius-2xl: var(--shape-radius-50);
19
+ --radius-pill: var(--shape-radius-pill);
20
+
21
+ /* shadows */
22
+ --shadow-none: var(--elevation-0);
23
+ --shadow-10: var(--elevation-10);
24
+ --shadow-20: var(--elevation-20);
25
+ --shadow-30: var(--elevation-30);
26
+ --shadow-40: var(--elevation-40);
27
+
28
+ /* expose primitives */
29
+ --color-ink-10: var(--ink-10);
30
+ --color-ink-20: var(--ink-20);
31
+ --color-ink-30: var(--ink-30);
32
+ --color-ink-40: var(--ink-40);
33
+ --color-ink-50: var(--ink-50);
34
+ --color-ink-60: var(--ink-60);
35
+ --color-ink-70: var(--ink-70);
36
+ --color-ink-80: var(--ink-80);
37
+ --color-ink-90: var(--ink-90);
38
+ --color-ink-100: var(--ink-100);
39
+
40
+ --color-brand-10: var(--brand-10);
41
+ --color-brand-20: var(--brand-20);
42
+ --color-brand-30: var(--brand-30);
43
+ --color-brand-40: var(--brand-40);
44
+ --color-brand-50: var(--brand-50);
45
+ --color-brand-60: var(--brand-60);
46
+ --color-brand-70: var(--brand-70);
47
+ --color-brand-80: var(--brand-80);
48
+ --color-brand-90: var(--brand-90);
49
+ --color-brand-100: var(--brand-100);
50
+
51
+ --color-accent-10: var(--accent-10);
52
+ --color-accent-20: var(--accent-20);
53
+ --color-accent-30: var(--accent-30);
54
+ --color-accent-40: var(--accent-40);
55
+ --color-accent-50: var(--accent-50);
56
+ --color-accent-60: var(--accent-60);
57
+ --color-accent-70: var(--accent-70);
58
+ --color-accent-80: var(--accent-80);
59
+ --color-accent-90: var(--accent-90);
60
+ --color-accent-100: var(--accent-100);
61
+
62
+ /* semantic exports */
63
+ --color-bg: var(--bg);
64
+ --color-surface-1: var(--surface-1);
65
+ --color-surface-2: var(--surface-2);
66
+ --color-surface-3: var(--surface-3);
67
+
68
+ --color-text-1: var(--text-1);
69
+ --color-text-2: var(--text-2);
70
+ --color-text-inverted: var(--text-inverted);
71
+ --color-muted: var(--muted);
72
+
73
+ --color-border: var(--border);
74
+ --color-divider: var(--divider);
75
+
76
+ --color-brand: var(--brand);
77
+ --color-brand-strong: var(--brand-strong);
78
+
79
+ --color-accent: var(--accent);
80
+ --color-accent-strong: var(--accent-strong);
81
+
82
+ --color-link: var(--link);
83
+ --color-link-hover: var(--link-hover);
84
+
85
+ --color-focus: var(--focus);
86
+ --focus-ring: var(--focus-ring);
87
+
88
+ --color-info: var(--info);
89
+ --color-success: var(--success);
90
+ --color-warning: var(--warning);
91
+ --color-danger: var(--danger);
92
+
93
+ --color-info-soft: var(--info-soft);
94
+ --color-success-soft: var(--success-soft);
95
+ --color-warning-soft: var(--warning-soft);
96
+ --color-danger-soft: var(--danger-soft);
97
+
98
+ --color-on-info: var(--on-info);
99
+ --color-on-success: var(--on-success);
100
+ --color-on-warning: var(--on-warning);
101
+ --color-on-danger: var(--on-danger);
102
+
103
+ --color-overlay: var(--overlay);
104
+
105
+ --color-disabled-fg: var(--disabled-fg);
106
+ --color-disabled-bg: var(--disabled-bg);
107
+ --color-disabled-border: var(--disabled-border);
108
+ }
@@ -0,0 +1,164 @@
1
+ @utility state-layer {
2
+ position: relative;
3
+ isolation: isolate;
4
+
5
+ --state-hover: color-mix(in oklab, currentColor, transparent 92%);
6
+ --state-active: color-mix(in oklab, currentColor, transparent 86%);
7
+
8
+ &::after{
9
+ content: "";
10
+ position: absolute;
11
+ inset: 0;
12
+ border-radius: inherit;
13
+ background: var(--state-hover);
14
+ opacity: 0;
15
+ transition: opacity 100ms ease;
16
+ pointer-events: none;
17
+ }
18
+
19
+ &:hover::after { opacity: 1; }
20
+
21
+ &:active::after{
22
+ background: var(--state-active);
23
+ opacity: 1;
24
+ }
25
+ }
26
+
27
+ @layer base {
28
+ html {
29
+ scroll-behavior: smooth;
30
+ background: var(--bg);
31
+ color: var(--text-1);
32
+ transition: background-color 0.3s ease, color 0.1s ease;
33
+
34
+ font-feature-settings: "tnum" 1, "lnum" 1;
35
+ -webkit-font-smoothing: antialiased;
36
+ -moz-osx-font-smoothing: grayscale;
37
+ }
38
+
39
+ body {
40
+ text-wrap: balance;
41
+ font: var(--p);
42
+ display: flex;
43
+ flex-direction: column;
44
+ min-height: 100vh;
45
+ }
46
+
47
+ h1 { font: var(--h1); @apply my-2; }
48
+ h2 { font: var(--h2); @apply my-2; }
49
+ h3 { font: var(--h3); @apply my-2; }
50
+
51
+ p {
52
+ @apply my-2;
53
+ white-space: normal;
54
+ word-break: break-word;
55
+ }
56
+
57
+ a {
58
+ color: var(--link);
59
+ text-decoration: none;
60
+ }
61
+ a:hover {
62
+ color: var(--link-hover);
63
+ text-decoration: underline;
64
+ }
65
+
66
+ :where(button,[role="button"],a,input,select,textarea,[tabindex]):focus-visible {
67
+ outline: none;
68
+ box-shadow: var(--focus-ring);
69
+ }
70
+ }
71
+
72
+ @layer components {
73
+ .card {
74
+ background: var(--surface-2);
75
+ border: 1px solid color-mix(in oklab, var(--border), transparent 45%);
76
+ border-radius: var(--radius-card);
77
+ box-shadow: var(--shadow-elevated);
78
+ }
79
+
80
+ .popover {
81
+ background: var(--surface-3);
82
+ border: 1px solid color-mix(in oklab, var(--border), transparent 40%);
83
+ border-radius: var(--radius-card);
84
+ box-shadow: var(--shadow-popover);
85
+ }
86
+
87
+ .shell {
88
+ background: var(--surface-1);
89
+ border-radius: var(--radius-shell);
90
+ box-shadow: var(--shadow-modal);
91
+ }
92
+
93
+ .panel {
94
+ background: var(--surface-2);
95
+ border-radius: var(--radius-shell);
96
+ box-shadow: var(--shadow-elevated);
97
+ }
98
+
99
+ .inset {
100
+ background: var(--surface-1);
101
+ border-radius: var(--radius-card);
102
+ box-shadow: inset 0 1px 0 color-mix(in oklab, var(--border), transparent 60%);
103
+ }
104
+
105
+ .chip {
106
+ background: color-mix(in oklab, var(--surface-2), var(--surface-3) 40%);
107
+ border-radius: var(--radius-chip);
108
+ box-shadow: var(--shadow-none);
109
+ color: var(--text-2);
110
+ padding: 0.25rem 0.75rem;
111
+ display: inline-flex;
112
+ align-items: center;
113
+ gap: 0.375rem;
114
+ }
115
+ }
116
+
117
+ @layer utilities {
118
+ .brand-gradient {
119
+ background: linear-gradient(90deg, var(--accent-strong) 0%, var(--accent) 30%);
120
+ -webkit-background-clip: text;
121
+ -webkit-text-fill-color: transparent;
122
+ }
123
+
124
+ .btn {
125
+ @apply state-layer inline-flex items-center justify-center gap-2 px-3.5 py-2.5
126
+ text-sm font-medium select-none cursor-pointer
127
+ transition-[background,color,box-shadow,transform] duration-150;
128
+ position: relative;
129
+ border-radius: var(--radius-btn);
130
+ box-shadow: var(--shadow-10);
131
+ }
132
+
133
+ .btn:disabled, .btn.disabled {
134
+ opacity: 0.5;
135
+ pointer-events: none;
136
+ }
137
+
138
+ .btn-primary {
139
+ background: var(--accent);
140
+ color: var(--text-inverted);
141
+ }
142
+
143
+ .btn-secondary {
144
+ border: 1px solid var(--border);
145
+ }
146
+
147
+ :root .prose code {
148
+ background: rgba(0, 0, 0, 0.08);
149
+ padding: 3px 3px 0;
150
+ border-radius: 4px;
151
+ }
152
+
153
+ .dark .prose code {
154
+ background: rgba(0, 0, 0, 0.35);
155
+ }
156
+
157
+ .prose pre code {
158
+ background: transparent;
159
+ }
160
+
161
+ .dark .prose pre code {
162
+ background: transparent;
163
+ }
164
+ }
@@ -0,0 +1,133 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap');
2
+ @import url('https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;600;700&display=swap');
3
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap');
4
+
5
+ :root {
6
+ /* Typography */
7
+ --font-primary: 'Inter', sans-serif;
8
+ --font-secondary: 'Fira Sans', sans-serif;
9
+ --font-mono: 'JetBrains Mono', 'Consolas', monospace;
10
+ --h1: 600 3rem/1.2em var(--font-secondary);
11
+ --h2: 600 2rem/1.2em var(--font-secondary);
12
+ --h3: 600 1.25rem/1.3em var(--font-secondary);
13
+ --p: 1rem/1.5em var(--font-primary);
14
+ --span: 1rem/1.0em var(--font-primary);
15
+
16
+ /* Radii */
17
+ --shape-radius-0: 0px;
18
+ --shape-radius-5: 0.125rem; /* 2px */
19
+ --shape-radius-10: 0.25rem; /* 4px */
20
+ --shape-radius-20: 0.5rem; /* 8px */
21
+ --shape-radius-30: 0.75rem; /* 12px */
22
+ --shape-radius-40: 1rem; /* 16px */
23
+ --shape-radius-50: 1.5rem; /* 24px */
24
+ --shape-radius-pill: 999px;
25
+
26
+ /* Neutral ramp */
27
+ --ink-10: oklch(0.92 0.043 258);
28
+ --ink-20: oklch(0.84 0.043 258);
29
+ --ink-30: oklch(0.76 0.043 258);
30
+ --ink-40: oklch(0.68 0.043 258);
31
+ --ink-50: oklch(0.60 0.035 258);
32
+ --ink-60: oklch(0.48 0.035 258);
33
+ --ink-70: oklch(0.40 0.035 258);
34
+ --ink-80: oklch(0.32 0.025 258);
35
+ --ink-90: oklch(0.24 0.025 258);
36
+ --ink-100: oklch(0.16 0.025 258);
37
+
38
+ /* Accent */
39
+ --accent-10: oklch(0.970 0.030 200);
40
+ --accent-20: oklch(0.940 0.045 200);
41
+ --accent-30: oklch(0.910 0.060 200);
42
+ --accent-40: oklch(0.880 0.075 200);
43
+ --accent-50: oklch(0.820 0.095 200);
44
+ --accent-60: oklch(0.760 0.110 200);
45
+ --accent-70: oklch(0.650 0.105 200);
46
+ --accent-80: oklch(0.560 0.090 200);
47
+ --accent-90: oklch(0.480 0.075 200);
48
+ --accent-100: oklch(0.400 0.060 200);
49
+
50
+ /* Brand ramp */
51
+ --brand-10: oklch(0.97 0.020 250);
52
+ --brand-20: oklch(0.93 0.035 250);
53
+ --brand-30: oklch(0.88 0.050 250);
54
+ --brand-40: oklch(0.82 0.070 250);
55
+ --brand-50: oklch(0.74 0.095 250);
56
+ --brand-60: oklch(0.66 0.120 250);
57
+ --brand-70: oklch(0.58 0.145 250);
58
+ --brand-80: oklch(0.50 0.135 250);
59
+ --brand-90: oklch(0.42 0.115 250);
60
+ --brand-100: oklch(0.34 0.095 250);
61
+
62
+ /* Functional ramps */
63
+ --info-10: oklch(0.970 0.028 230);
64
+ --info-20: oklch(0.940 0.042 230);
65
+ --info-30: oklch(0.910 0.056 230);
66
+ --info-40: oklch(0.880 0.070 230);
67
+ --info-50: oklch(0.820 0.090 230);
68
+ --info-60: oklch(0.760 0.105 230);
69
+ --info-70: oklch(0.660 0.110 230);
70
+ --info-80: oklch(0.560 0.095 230);
71
+ --info-90: oklch(0.470 0.080 230);
72
+
73
+ --success-10: oklch(0.920 0.042 145);
74
+ --success-20: oklch(0.876 0.060 145);
75
+ --success-30: oklch(0.832 0.078 145);
76
+ --success-40: oklch(0.788 0.094 145);
77
+ --success-50: oklch(0.744 0.109 145);
78
+ --success-60: oklch(0.700 0.120 145);
79
+ --success-70: oklch(0.600 0.100 145);
80
+ --success-80: oklch(0.500 0.080 145);
81
+ --success-90: oklch(0.400 0.060 145);
82
+
83
+ --warning-10: oklch(0.970 0.042 80);
84
+ --warning-20: oklch(0.932 0.060 80);
85
+ --warning-30: oklch(0.894 0.078 80);
86
+ --warning-40: oklch(0.856 0.094 80);
87
+ --warning-50: oklch(0.818 0.109 80);
88
+ --warning-60: oklch(0.780 0.120 80);
89
+ --warning-70: oklch(0.680 0.100 80);
90
+ --warning-80: oklch(0.580 0.080 80);
91
+ --warning-90: oklch(0.480 0.060 80);
92
+
93
+ --danger-10: oklch(0.880 0.056 28);
94
+ --danger-20: oklch(0.836 0.080 28);
95
+ --danger-30: oklch(0.792 0.104 28);
96
+ --danger-40: oklch(0.748 0.125 28);
97
+ --danger-50: oklch(0.704 0.145 28);
98
+ --danger-60: oklch(0.660 0.160 28);
99
+ --danger-70: oklch(0.560 0.133 28);
100
+ --danger-80: oklch(0.460 0.107 28);
101
+ --danger-90: oklch(0.360 0.080 28);
102
+
103
+ /* Elevation */
104
+ --elevation-0: none;
105
+ --elevation-10:
106
+ 0 1px 3px oklch(0.55 0 0 / 0.08),
107
+ 0 1px 2px oklch(0.55 0 0 / 0.12);
108
+ --elevation-20:
109
+ 0 4px 8px oklch(0.55 0 0 / 0.08),
110
+ 0 2px 4px oklch(0.55 0 0 / 0.06);
111
+ --elevation-30:
112
+ 0 10px 20px oklch(0.55 0 0 / 0.16),
113
+ 0 3px 8px oklch(0.55 0 0 / 0.10);
114
+ --elevation-40:
115
+ 0 18px 36px oklch(0.55 0 0 / 0.22),
116
+ 0 6px 12px oklch(0.55 0 0 / 0.12);
117
+ }
118
+
119
+ .dark {
120
+ --elevation-0: none;
121
+ --elevation-10:
122
+ 0 1px 2px oklch(0.25 0 0 / 0.35),
123
+ 0 0 0 1px oklch(0.22 0 0 / 0.35);
124
+ --elevation-20:
125
+ 0 4px 10px oklch(0.25 0 0 / 0.38),
126
+ 0 1px 3px oklch(0.25 0 0 / 0.28);
127
+ --elevation-30:
128
+ 0 12px 24px oklch(0.25 0 0 / 0.42),
129
+ 0 4px 10px oklch(0.25 0 0 / 0.32);
130
+ --elevation-40:
131
+ 0 20px 40px oklch(0.25 0 0 / 0.48),
132
+ 0 6px 18px oklch(0.25 0 0 / 0.32);
133
+ }
@@ -0,0 +1,120 @@
1
+ :root { color-scheme: light; }
2
+ .dark { color-scheme: dark; }
3
+
4
+ :root {
5
+ /* Surfaces */
6
+ --bg: var(--ink-10);
7
+ --surface-1: color-mix(in oklab, var(--ink-10), black 12%);
8
+ --surface-2: color-mix(in oklab, var(--ink-10), black 8%);
9
+ --surface-3: color-mix(in oklab, var(--ink-10), black 4%);
10
+
11
+ /* Typography */
12
+ --text-1: var(--ink-100);
13
+ --text-2: var(--ink-80);
14
+ --muted: var(--ink-70);
15
+ --text-inverted: var(--ink-10);
16
+
17
+ /* Borders / dividers */
18
+ --border: var(--ink-60);
19
+ --divider: color-mix(in oklab, var(--border), transparent 55%);
20
+
21
+ /* Brand + accent roles */
22
+ --brand: var(--brand-70);
23
+ --brand-strong: var(--brand-90);
24
+
25
+ --accent: var(--accent-70);
26
+ --accent-strong: var(--accent-80);
27
+
28
+ /* UI roles */
29
+ --link: var(--accent);
30
+ --link-hover: color-mix(in oklab, var(--link), white 14%);
31
+ --focus: var(--brand);
32
+ --focus-ring: 0 0 0 3px color-mix(in oklab, var(--focus), transparent 60%);
33
+
34
+ /* Status roles */
35
+ --info: var(--info-60);
36
+ --success: var(--success-60);
37
+ --warning: var(--warning-60);
38
+ --danger: var(--danger-60);
39
+
40
+ --info-soft: color-mix(in oklab, var(--info), var(--bg) 85%);
41
+ --success-soft: color-mix(in oklab, var(--success), var(--bg) 85%);
42
+ --warning-soft: color-mix(in oklab, var(--warning), var(--bg) 85%);
43
+ --danger-soft: color-mix(in oklab, var(--danger), var(--bg) 85%);
44
+
45
+ /* On-colors */
46
+ --on-info: oklch(0.16 0 0);
47
+ --on-success: oklch(0.16 0 0);
48
+ --on-warning: oklch(0.16 0 0);
49
+ --on-danger: oklch(0.16 0 0);
50
+
51
+ /* Interaction tokens */
52
+ --surface-hover: color-mix(in oklab, var(--surface-1), black 10%);
53
+ --surface-active: color-mix(in oklab, var(--surface-1), black 12%);
54
+
55
+ /* Overlay */
56
+ --overlay: oklch(0.16 0 0 / 0.40);
57
+
58
+ /* Elevation */
59
+ --shadow-none: var(--elevation-0);
60
+ --shadow-elevated: var(--elevation-20);
61
+ --shadow-popover: var(--elevation-30);
62
+ --shadow-modal: var(--elevation-40);
63
+
64
+ /* Shapes */
65
+ --radius-chip: var(--shape-radius-pill);
66
+ --radius-btn: var(--shape-radius-20);
67
+ --radius-input: var(--shape-radius-20);
68
+ --radius-card: var(--shape-radius-30);
69
+ --radius-shell: var(--shape-radius-40);
70
+
71
+ /* Disabled */
72
+ --disabled-fg: color-mix(in oklab, var(--text-2), transparent 45%);
73
+ --disabled-bg: color-mix(in oklab, var(--surface-2), transparent 35%);
74
+ --disabled-border: color-mix(in oklab, var(--border), transparent 60%);
75
+ }
76
+
77
+ .dark {
78
+ --bg: var(--ink-90);
79
+ --surface-1: color-mix(in oklab, var(--ink-90), white 6%);
80
+ --surface-2: color-mix(in oklab, var(--ink-90), white 10%);
81
+ --surface-3: color-mix(in oklab, var(--ink-90), white 14%);
82
+
83
+ --text-1: var(--ink-10);
84
+ --text-2: var(--ink-20);
85
+ --muted: var(--ink-30);
86
+ --text-inverted: var(--ink-90);
87
+
88
+ --border: var(--ink-40);
89
+ --divider: color-mix(in oklab, var(--border), transparent 40%);
90
+
91
+ --brand: var(--brand-70);
92
+ --brand-strong: var(--brand-60);
93
+
94
+ --accent: var(--accent-70);
95
+ --accent-strong: var(--accent-60);
96
+
97
+ --link: var(--accent);
98
+ --link-hover: color-mix(in oklab, var(--link), white 18%);
99
+ --focus: var(--brand);
100
+ --focus-ring: 0 0 0 3px color-mix(in oklab, var(--focus), transparent 60%);
101
+
102
+ --info: var(--info-70);
103
+ --success: var(--success-70);
104
+ --warning: var(--warning-70);
105
+ --danger: var(--danger-70);
106
+
107
+ --surface-hover: color-mix(in oklab, var(--surface-1), white 6%);
108
+ --surface-active: color-mix(in oklab, var(--surface-1), white 8%);
109
+
110
+ --overlay: oklch(0.00 0 0 / 0.55);
111
+
112
+ --on-info: oklch(0.12 0 0);
113
+ --on-success: oklch(0.12 0 0);
114
+ --on-warning: oklch(0.12 0 0);
115
+ --on-danger: oklch(0.12 0 0);
116
+
117
+ --disabled-fg: color-mix(in oklab, var(--text-2), transparent 55%);
118
+ --disabled-bg: color-mix(in oklab, var(--surface-2), transparent 35%);
119
+ --disabled-border: color-mix(in oklab, var(--border), transparent 55%);
120
+ }
@@ -0,0 +1,22 @@
1
+ .custom-scrollbar {
2
+ @apply scrollbar-thin;
3
+ scrollbar-color: theme(colors.ink.70) transparent;
4
+ overscroll-behavior: contain;
5
+ scrollbar-gutter: stable both-edges;
6
+ }
7
+
8
+ .custom-scrollbar::-webkit-scrollbar {
9
+ @apply w-2 h-2;
10
+ }
11
+
12
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
13
+ @apply bg-ink-90;
14
+ }
15
+
16
+ .custom-scrollbar::-webkit-scrollbar-track {
17
+ @apply bg-transparent;
18
+ }
19
+
20
+ .custom-scrollbar::-webkit-scrollbar-button{
21
+ display:none;
22
+ }
package/dist/index.d.ts CHANGED
@@ -151,16 +151,19 @@ type UIFail = ResultError<string> & {
151
151
  type UIResult<T> = UIOk<T> | UIFail;
152
152
  declare const ui: {
153
153
  success: <T>(value: T, ...effects: Instruction[]) => UIResult<T>;
154
- failure: (error: string, ...extraEffects: Instruction[]) => UIResult<never>;
154
+ failure: (error: string, ...effects: Instruction[]) => UIResult<never>;
155
155
  };
156
156
 
157
157
  type OptimisticSnapshot = {
158
158
  rollback: () => void | Promise<void>;
159
159
  };
160
+ type MutationFn<Args, Res> = (args: Args) => Promise<UIResult<Res>>;
161
+ type OptimisticUpdateFn<Args> = (args: Args, ctx: InstructionContext) => Promise<OptimisticSnapshot | void> | OptimisticSnapshot | void;
162
+ type OnSuccessFn<Res> = (data: Res) => void;
160
163
  type ResponsiveMutation<Args, Res> = {
161
- mutationFn: (args: Args) => Promise<UIResult<Res>>;
162
- optimistic?: (args: Args, ctx: InstructionContext) => Promise<OptimisticSnapshot | void> | OptimisticSnapshot | void;
163
- onSuccess?: (data: Res) => void;
164
+ mutationFn: MutationFn<Args, Res>;
165
+ optimistic?: OptimisticUpdateFn<Args>;
166
+ onSuccess?: OnSuccessFn<Res>;
164
167
  };
165
168
 
166
169
  declare function useResponsiveMutation<Args, Res>(responsiveMutation: ResponsiveMutation<Args, Res>, queryClient: QueryClient): _tanstack_react_query.UseMutationResult<UIOk<Res>, UIFail, Args, OptimisticSnapshot | undefined>;
@@ -356,6 +359,20 @@ interface InputProps {
356
359
  }
357
360
  declare const AuthFormInputField: react__default.FC<InputProps>;
358
361
 
362
+ type RequireAuthProps = {
363
+ guarded?: ReactNode;
364
+ loadingPlaceholder?: ReactNode;
365
+ errorPlaceholder?: ReactNode;
366
+ };
367
+ type RedirectIfAuthedProps = {
368
+ redirectTo?: string;
369
+ loadingPlaceholder?: ReactNode;
370
+ nonAuthedPlaceholder?: ReactNode;
371
+ errorPlaceholder?: ReactNode;
372
+ };
373
+ declare function RequireAuth({ guarded, loadingPlaceholder, errorPlaceholder }: RequireAuthProps): react_jsx_runtime.JSX.Element;
374
+ declare function RedirectIfAuthed({ redirectTo, loadingPlaceholder, nonAuthedPlaceholder, errorPlaceholder }: RedirectIfAuthedProps): react_jsx_runtime.JSX.Element;
375
+
359
376
  type AuthFixtures = {
360
377
  meError?: HttpError;
361
378
  loginError?: HttpError;
@@ -375,4 +392,4 @@ declare class MockAuthHttpClient extends MockHttpClient {
375
392
  private registerAuthRoutes;
376
393
  }
377
394
 
378
- export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthFormInputField, AuthProvider, type AuthState, AuthStateCtx, type CacheInstruction, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type ErrorResponse, type GenericResponse, type HttpClient, HttpError, type HttpMethod, type HttpResponse, type Instruction, type InstructionContext, MockAuthHttpClient, MockHttpClient, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OptimisticSnapshot, type RequestConfig, type ResolvedToastTheme, type ResponsiveMutation, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, type UIFail, type UIOk, type UIResult, type User, authController, controllerFactory, createAuthController, httpClient as fetchHttpClient, notifierController, resolveToastTheme, ui, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useResponsiveMutation };
395
+ export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthFormInputField, AuthProvider, type AuthState, AuthStateCtx, type CacheInstruction, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type ErrorResponse, type GenericResponse, type HttpClient, HttpError, type HttpMethod, type HttpResponse, type Instruction, type InstructionContext, MockAuthHttpClient, MockHttpClient, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, RedirectIfAuthed, type RedirectIfAuthedProps, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, type UIFail, type UIOk, type UIResult, type User, authController, controllerFactory, createAuthController, httpClient as fetchHttpClient, notifierController, resolveToastTheme, ui, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useResponsiveMutation };
package/dist/index.js CHANGED
@@ -1,26 +1,14 @@
1
1
  // src/util/responsive-query/ui-result.ts
2
- import { v4 as uuid } from "uuid";
3
2
  var ui = {
4
3
  success: (value, ...effects) => ({
5
4
  ok: true,
6
5
  value,
7
6
  effects
8
7
  }),
9
- failure: (error, ...extraEffects) => ({
8
+ failure: (error, ...effects) => ({
10
9
  ok: false,
11
10
  error,
12
- effects: [
13
- {
14
- type: "notify",
15
- notification: {
16
- id: uuid(),
17
- title: "Error",
18
- content: error,
19
- variant: "error"
20
- }
21
- },
22
- ...extraEffects
23
- ]
11
+ effects
24
12
  })
25
13
  };
26
14
 
@@ -921,6 +909,35 @@ var AuthFormInputField = ({ id, label, type, value, onChange, placeholder, class
921
909
  ] });
922
910
  };
923
911
 
912
+ // src/feature/auth/interface/web/react/auth-route-guards.tsx
913
+ import { Navigate, Outlet, useLocation } from "react-router-dom";
914
+ import { Fragment, jsx as jsx6 } from "react/jsx-runtime";
915
+ function RequireAuth({ guarded, loadingPlaceholder, errorPlaceholder }) {
916
+ const auth = useAuth();
917
+ const location = useLocation();
918
+ if (auth.status === "loading") {
919
+ return /* @__PURE__ */ jsx6(Fragment, { children: loadingPlaceholder ?? null });
920
+ }
921
+ if (auth.status === "error") {
922
+ return /* @__PURE__ */ jsx6(Fragment, { children: errorPlaceholder ?? loadingPlaceholder ?? null });
923
+ }
924
+ if (auth.status === "unauthenticated") {
925
+ return /* @__PURE__ */ jsx6(Navigate, { to: "/login", replace: true, state: { from: location } });
926
+ }
927
+ return guarded ? /* @__PURE__ */ jsx6(Fragment, { children: guarded }) : /* @__PURE__ */ jsx6(Outlet, {});
928
+ }
929
+ function RedirectIfAuthed({ redirectTo, loadingPlaceholder, nonAuthedPlaceholder, errorPlaceholder }) {
930
+ const auth = useAuth();
931
+ if (auth.status === "loading") {
932
+ return /* @__PURE__ */ jsx6(Fragment, { children: loadingPlaceholder ?? null });
933
+ }
934
+ if (auth.status === "error") {
935
+ return /* @__PURE__ */ jsx6(Fragment, { children: errorPlaceholder ?? loadingPlaceholder ?? null });
936
+ }
937
+ if (auth.status === "authenticated") return /* @__PURE__ */ jsx6(Navigate, { to: redirectTo ?? "/", replace: true });
938
+ return nonAuthedPlaceholder ? /* @__PURE__ */ jsx6(Fragment, { children: nonAuthedPlaceholder }) : /* @__PURE__ */ jsx6(Outlet, {});
939
+ }
940
+
924
941
  // src/feature/auth/infra/mock-auth-http-client.ts
925
942
  function httpResponse(data, status = 200) {
926
943
  return { data, status, headers: {} };
@@ -1006,6 +1023,8 @@ export {
1006
1023
  MockHttpClient,
1007
1024
  NotificationHost,
1008
1025
  NotifierController,
1026
+ RedirectIfAuthed,
1027
+ RequireAuth,
1009
1028
  authController,
1010
1029
  controllerFactory,
1011
1030
  createAuthController,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,6 +8,14 @@
8
8
  ".": {
9
9
  "types": "./dist/index.d.ts",
10
10
  "default": "./dist/index.js"
11
+ },
12
+ "./css": {
13
+ "import": "./dist/css/base-theme.css",
14
+ "default": "./dist/css/base-theme.css"
15
+ },
16
+ "./css/*": {
17
+ "import": "./dist/css/*",
18
+ "default": "./dist/css/*"
11
19
  }
12
20
  },
13
21
  "files": [
@@ -23,6 +31,7 @@
23
31
  "lucide-react": "^0.555.0",
24
32
  "react-router-dom": "^7.10.1",
25
33
  "react-toastify": "^11.0.5",
34
+ "tailwind-scrollbar": "^4.0.2",
26
35
  "uuid": "^13.0.0",
27
36
  "@hexdspace/util": "0.0.25"
28
37
  },
@@ -33,10 +42,14 @@
33
42
  "devDependencies": {
34
43
  "@tanstack/react-query": "^5.90.11",
35
44
  "@types/react": "^19.2.7",
36
- "react": "^19.2.0"
45
+ "autoprefixer": "^10.4.22",
46
+ "postcss": "^8.5.6",
47
+ "react": "^19.2.0",
48
+ "tailwindcss": "^4.1.17"
37
49
  },
38
50
  "scripts": {
39
- "build": "tsup src/index.ts --dts --format esm --clean",
51
+ "build": "tsup src/index.ts --dts --format esm --clean && pnpm run build:css",
52
+ "build:css": "mkdir -p dist/css && cp -R src/feature/theme/css/* dist/css/",
40
53
  "test": "vitest"
41
54
  }
42
55
  }