@astratra/saas-kit-ui 1.1.0 → 1.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.
- package/README.md +2 -2
- package/package.json +21 -4
- package/src/components/FeedbackBar.js +19 -2
- package/src/index.d.ts +60 -0
- package/src/lib/api.d.ts +15 -0
- package/src/styles/global.css +9 -0
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ Utilisez ce paquet si `AstratraDashboardApp` vous convient tel quel ; utilisez `
|
|
|
68
68
|
|
|
69
69
|
MIT.
|
|
70
70
|
|
|
71
|
-
## FeedbackBar :
|
|
71
|
+
## FeedbackBar : pouces sous une réponse d’IA
|
|
72
72
|
|
|
73
73
|
Le même composant que dans `@astratra/native-ui`, pour le web. Contrôlé :
|
|
74
74
|
l'application garde `value` et parle à son serveur (par exemple
|
|
@@ -88,7 +88,7 @@ import { FeedbackBar } from '@astratra/saas-kit-ui';
|
|
|
88
88
|
Le pouce haut part aussitôt ; le pouce bas ouvre un panneau (raison,
|
|
89
89
|
commentaire facultatif) ; appuyer sur le pouce choisi le retire. Libellés par
|
|
90
90
|
défaut en anglais et en français (`locale`), remplaçables un par un (`labels`) ;
|
|
91
|
-
raisons ajoutables (`reasons`) ; `icons` remplace les émojis ; `haptics` est une
|
|
91
|
+
raisons ajoutables (`reasons`) ; `icons` remplace les pouces dessinés (contour SVG, plein une fois choisi, jamais d'émojis) ; `haptics` est une
|
|
92
92
|
fonction facultative (rien par défaut). Accessibilité : groupe nommé, boutons à
|
|
93
93
|
`aria-pressed`, puces `radio`, panneau `dialog`, Échap le ferme. Le style vient
|
|
94
94
|
des classes `.astratra-feedback*` de `styles.css` et des variables CSS du kit.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astratra/saas-kit-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Reusable React dashboard shell for Astratra SaaS applications, plus a thumbs up/down feedback bar for AI answers.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20"
|
|
@@ -9,8 +9,14 @@
|
|
|
9
9
|
"main": "src/index.jsx",
|
|
10
10
|
"module": "src/index.jsx",
|
|
11
11
|
"exports": {
|
|
12
|
-
".":
|
|
13
|
-
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./src/index.d.ts",
|
|
14
|
+
"default": "./src/index.jsx"
|
|
15
|
+
},
|
|
16
|
+
"./api": {
|
|
17
|
+
"types": "./src/lib/api.d.ts",
|
|
18
|
+
"default": "./src/lib/api.js"
|
|
19
|
+
},
|
|
14
20
|
"./styles.css": "./src/styles/global.css"
|
|
15
21
|
},
|
|
16
22
|
"files": [
|
|
@@ -35,5 +41,16 @@
|
|
|
35
41
|
},
|
|
36
42
|
"sideEffects": [
|
|
37
43
|
"**/*.css"
|
|
38
|
-
]
|
|
44
|
+
],
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/react": "^19.2.18"
|
|
47
|
+
},
|
|
48
|
+
"types": "src/index.d.ts",
|
|
49
|
+
"typesVersions": {
|
|
50
|
+
"*": {
|
|
51
|
+
"api": [
|
|
52
|
+
"src/lib/api.d.ts"
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
39
56
|
}
|
|
@@ -8,7 +8,24 @@ import {
|
|
|
8
8
|
resolveFeedbackLabels
|
|
9
9
|
} from '../lib/feedbackBar.js';
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The thumbs are drawn, never emoji (an emoji changes with the system and looks out of place in a
|
|
13
|
+
* product). One outline on a 24 grid; down is the same hand turned upside down. Filled once chosen.
|
|
14
|
+
*/
|
|
15
|
+
export const THUMB_PATH = 'M7 21H4.5A1.5 1.5 0 0 1 3 19.5v-8A1.5 1.5 0 0 1 4.5 10H7M7 21V10l4.2-6.3A1.6 1.6 0 0 1 14 4.6V9h5a2 2 0 0 1 2 2.4l-1.5 7.9A2 2 0 0 1 17.5 21H7';
|
|
16
|
+
|
|
17
|
+
function thumbIcon(rating, filled) {
|
|
18
|
+
return h('svg', {
|
|
19
|
+
'aria-hidden': 'true', focusable: 'false', viewBox: '0 0 24 24', width: 18, height: 18,
|
|
20
|
+
className: 'astratra-feedback__icon', fill: 'none', stroke: 'currentColor',
|
|
21
|
+
strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round'
|
|
22
|
+
}, h('path', {
|
|
23
|
+
d: THUMB_PATH,
|
|
24
|
+
fill: filled ? 'currentColor' : 'none',
|
|
25
|
+
fillOpacity: filled ? 0.9 : undefined,
|
|
26
|
+
transform: rating === 'down' ? 'matrix(1 0 0 -1 0 24)' : undefined
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
12
29
|
|
|
13
30
|
/**
|
|
14
31
|
* Thumbs up / thumbs down under an AI answer. Controlled: the app keeps
|
|
@@ -45,7 +62,7 @@ export default function FeedbackBar({
|
|
|
45
62
|
const thumb = (rating) => h('button', {
|
|
46
63
|
key: rating, type: 'button', disabled, 'aria-pressed': value === rating, 'aria-label': words[rating], title: words[rating],
|
|
47
64
|
className: 'astratra-feedback__thumb', 'data-rating': rating, onClick: () => press(rating)
|
|
48
|
-
}, icons?.[rating] ??
|
|
65
|
+
}, icons?.[rating] ?? thumbIcon(rating, value === rating));
|
|
49
66
|
|
|
50
67
|
const options = feedbackReasonOptions({ reasons, labels: words, selected: reason });
|
|
51
68
|
return h('div', { id, role: 'group', 'aria-label': words.group, className: ['astratra-feedback', className].filter(Boolean).join(' '), style },
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { ApiFetchOptions } from './lib/api';
|
|
3
|
+
export { ApiError, apiFetch } from './lib/api';
|
|
4
|
+
export type { ApiFetchOptions } from './lib/api';
|
|
5
|
+
export default function AstratraDashboardApp(): ReactElement;
|
|
6
|
+
export { AstratraDashboardApp };
|
|
7
|
+
export interface AuthUser { email?: string; role?: string; [key: string]: unknown }
|
|
8
|
+
export interface AuthValue {
|
|
9
|
+
isAuthenticated: boolean;
|
|
10
|
+
token: string | null;
|
|
11
|
+
user: AuthUser | null;
|
|
12
|
+
login(input: { email: string; password: string }): Promise<AuthUser>;
|
|
13
|
+
logout(): void;
|
|
14
|
+
request<T = unknown>(path: string, options?: ApiFetchOptions): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
export function AuthProvider(props: { children?: ReactNode }): ReactElement;
|
|
17
|
+
export function useAuth(): AuthValue;
|
|
18
|
+
export type DashboardView = 'dashboard' | 'users' | 'settings';
|
|
19
|
+
export function Layout(props: { activeView: DashboardView; onNavigate: (view: DashboardView) => void; children?: ReactNode }): ReactElement;
|
|
20
|
+
export function Notice(props: { tone?: 'neutral' | 'error' | 'success'; children?: ReactNode }): ReactElement | null;
|
|
21
|
+
export function DashboardScreen(): ReactElement;
|
|
22
|
+
export function LoginScreen(props: { onLoggedIn: () => void }): ReactElement;
|
|
23
|
+
export function SettingsScreen(): ReactElement;
|
|
24
|
+
export function UsersScreen(): ReactElement;
|
|
25
|
+
export type FeedbackRating = 'up' | 'down';
|
|
26
|
+
export type FeedbackReason = 'inaccurate' | 'incomplete' | 'off_topic' | 'wrong_source' | 'too_long' | 'unsafe' | 'other';
|
|
27
|
+
export interface FeedbackPayload { rating: FeedbackRating; reason?: string; comment?: string }
|
|
28
|
+
export interface FeedbackLabels {
|
|
29
|
+
group: string; up: string; down: string; sheetTitle: string;
|
|
30
|
+
commentLabel: string; commentPlaceholder: string; submit: string; cancel: string;
|
|
31
|
+
reasons: Readonly<Record<string, string>>;
|
|
32
|
+
counter: (used: number, max: number) => string;
|
|
33
|
+
}
|
|
34
|
+
export type FeedbackLabelOverrides = Partial<FeedbackLabels>;
|
|
35
|
+
export const FEEDBACK_COMMENT_MAX: 500;
|
|
36
|
+
export const FEEDBACK_REASONS: readonly FeedbackReason[];
|
|
37
|
+
export const FEEDBACK_LABELS: Readonly<{ en: Readonly<FeedbackLabels>; fr: Readonly<FeedbackLabels> }>;
|
|
38
|
+
export function resolveFeedbackLabels(options?: { locale?: string; labels?: FeedbackLabelOverrides }): FeedbackLabels;
|
|
39
|
+
export type FeedbackAction = { type: 'none' } | { type: 'remove' } | { type: 'ask' } | { type: 'submit'; payload: { rating: 'up' } };
|
|
40
|
+
export function feedbackPress(value: FeedbackRating | null | undefined, rating: unknown): FeedbackAction;
|
|
41
|
+
export function clampComment(text: unknown, max?: number): string;
|
|
42
|
+
export function buildFeedbackPayload(options: { rating: FeedbackRating; reason?: string | null; comment?: string; reasons?: readonly string[]; maxComment?: number }): FeedbackPayload;
|
|
43
|
+
export function feedbackReasonOptions(options: { reasons?: readonly string[]; labels: FeedbackLabels; selected?: string | null }): { id: string; label: string; selected: boolean }[];
|
|
44
|
+
export interface FeedbackBarProps {
|
|
45
|
+
value?: FeedbackRating | null;
|
|
46
|
+
onSubmit?: (payload: FeedbackPayload) => void;
|
|
47
|
+
onRemove?: () => void;
|
|
48
|
+
disabled?: boolean;
|
|
49
|
+
reasons?: readonly string[];
|
|
50
|
+
maxComment?: number;
|
|
51
|
+
labels?: FeedbackLabelOverrides;
|
|
52
|
+
locale?: string;
|
|
53
|
+
icons?: { up?: ReactNode; down?: ReactNode };
|
|
54
|
+
haptics?: false | (() => void);
|
|
55
|
+
defaultOpen?: boolean;
|
|
56
|
+
className?: string;
|
|
57
|
+
style?: CSSProperties;
|
|
58
|
+
id?: string;
|
|
59
|
+
}
|
|
60
|
+
export function FeedbackBar(props: FeedbackBarProps): ReactElement;
|
package/src/lib/api.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ApiFetchOptions {
|
|
2
|
+
apiUrl?: string;
|
|
3
|
+
token?: string | null;
|
|
4
|
+
method?: string;
|
|
5
|
+
body?: unknown;
|
|
6
|
+
fetcher?: typeof fetch;
|
|
7
|
+
onUnauthorized?: () => void;
|
|
8
|
+
}
|
|
9
|
+
export class ApiError extends Error {
|
|
10
|
+
constructor(message: string, options?: { status?: number; data?: unknown; error?: unknown });
|
|
11
|
+
status?: number;
|
|
12
|
+
data?: unknown;
|
|
13
|
+
error?: unknown;
|
|
14
|
+
}
|
|
15
|
+
export function apiFetch<T = unknown>(path: string, options?: ApiFetchOptions): Promise<T>;
|
package/src/styles/global.css
CHANGED
|
@@ -114,10 +114,19 @@ h3 {
|
|
|
114
114
|
border-radius: 999px;
|
|
115
115
|
background: transparent;
|
|
116
116
|
cursor: pointer;
|
|
117
|
+
color: var(--text, currentColor);
|
|
117
118
|
opacity: 0.7;
|
|
118
119
|
transition: opacity 120ms, background 120ms;
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
.astratra-feedback__icon {
|
|
123
|
+
display: block;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.astratra-feedback__thumb[aria-pressed="true"] .astratra-feedback__icon {
|
|
127
|
+
color: var(--lime, #d9ff66);
|
|
128
|
+
}
|
|
129
|
+
|
|
121
130
|
.astratra-feedback__thumb:hover:not(:disabled),
|
|
122
131
|
.astratra-feedback__thumb:focus-visible {
|
|
123
132
|
opacity: 1;
|